#remotes::install_github("braverock/FactorAnalytics",  build_vignettes = TRUE, force = TRUE)
pacman::p_load(tidyverse,tidyquant,FFdownload,FactorAnalytics,PerformanceAnalytics,PortfolioAnalytics,nloptr)

Please remember to put your assignment solutions in rmd format using many chunks and putting readable text in between, similar to my examples given in Research Methods and Assignment 1!

For all exercises: Please use the Assignment-Forum to post your questions, I will try my best to help you along!

Exercise 1: Analysing the CAPM

In this exercise we want to estimate the CAPM. Please read carefully through the two documents provided (right hand side: files). Then we start to collect the necessary data:

  1. From Datastream get the last 10 years of data from the 100 stocks of the S&P100 using the list LS&P100I (S&P 100): total return index (RI) and market cap (MV)
library(readxl)
sp100_daily_RI <- read_excel("sp100 daily RI_2.xlsx")
head(sp100_daily_RI, n=10)
library(readxl)
sp100_monthly_MV <- read_excel("sp100 monthly MV.xlsx")
head(sp100_monthly_MV, n=10)
  1. Further import the Fama-French-Factors from Kenneth Frenchs homepage (monthly, e.g. using FFdownload). From both datasets we select data for the last (available) 60 months, calculate returns (simple percentage) for the US-Stocks and eliminate those stocks that have NAs for this period.
 tempf <- tempfile(fileext = ".RData"); tempd <- tempdir(); temptxt <- tempfile(fileext = ".txt")
 inputlist <- c("F-F_Research_Data_Factors","F-F_Market_Beta")
 FFdownload(exclude_daily=TRUE,tempdir=tempd,download=TRUE,download_only=FALSE,inputlist=inputlist)
Step 1: getting list of all the csv-zip-files!

Step 2: Downloading 2 zip-files

trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/F-F_Research_Data_Factors_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/ME_Breakpoints_CSV.zip'
Step 3: Start processing 2 csv-files

  |                                                                                                       
  |                                                                                                 |   0%
  |                                                                                                       
  |================================================                                                 |  50%
  |                                                                                                       
  |=================================================================================================| 100%
 tempf2 <- tempfile(fileext = ".RData"); tempd2 <- tempdir() 
 FFdownload(output_file = tempf2,tempdir = tempd2,exclude_daily = TRUE, download = TRUE, download_only=FALSE, listsave=temptxt)
Step 1: getting list of all the csv-zip-files!

Step 2: Downloading 193 zip-files

trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/F-F_Research_Data_Factors_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/F-F_Research_Data_Factors_weekly_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/F-F_Research_Data_5_Factors_2x3_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Portfolios_Formed_on_ME_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Portfolios_Formed_on_ME_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Portfolios_Formed_on_BE-ME_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Portfolios_Formed_on_BE-ME_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Portfolios_Formed_on_OP_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Portfolios_Formed_on_OP_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Portfolios_Formed_on_INV_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Portfolios_Formed_on_INV_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/6_Portfolios_2x3_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/6_Portfolios_2x3_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/6_Portfolios_2x3_weekly_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/25_Portfolios_5x5_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/25_Portfolios_5x5_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/100_Portfolios_10x10_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/100_Portfolios_10x10_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/6_Portfolios_ME_OP_2x3_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/6_Portfolios_ME_OP_2x3_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/25_Portfolios_ME_OP_5x5_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/25_Portfolios_ME_OP_5x5_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/100_Portfolios_ME_OP_10x10_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/100_Portfolios_10x10_ME_OP_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/6_Portfolios_ME_INV_2x3_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/6_Portfolios_ME_INV_2x3_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/25_Portfolios_ME_INV_5x5_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/25_Portfolios_ME_INV_5x5_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/100_Portfolios_ME_INV_10x10_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/100_Portfolios_10x10_ME_INV_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/25_Portfolios_BEME_OP_5x5_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/25_Portfolios_BEME_OP_5x5_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/25_Portfolios_BEME_INV_5x5_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/25_Portfolios_BEME_INV_5x5_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/25_Portfolios_OP_INV_5x5_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/25_Portfolios_OP_INV_5x5_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/32_Portfolios_ME_BEME_OP_2x4x4_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/32_Portfolios_ME_BEME_OP_2x4x4_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/32_Portfolios_ME_BEME_INV_2x4x4_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/32_Portfolios_ME_BEME_INV_2x4x4_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/32_Portfolios_ME_OP_INV_2x4x4_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/32_Portfolios_ME_OP_INV_2x4x4_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Portfolios_Formed_on_E-P_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Portfolios_Formed_on_E-P_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Portfolios_Formed_on_CF-P_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Portfolios_Formed_on_CF-P_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Portfolios_Formed_on_D-P_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Portfolios_Formed_on_D-P_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/6_Portfolios_ME_EP_2x3_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/6_Portfolios_ME_EP_2x3_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/6_Portfolios_ME_CFP_2x3_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/6_Portfolios_ME_CFP_2x3_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/6_Portfolios_ME_DP_2x3_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/6_Portfolios_ME_DP_2x3_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/F-F_Momentum_Factor_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/6_Portfolios_ME_Prior_12_2_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/25_Portfolios_ME_Prior_12_2_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/10_Portfolios_Prior_12_2_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/F-F_ST_Reversal_Factor_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/6_Portfolios_ME_Prior_1_0_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/25_Portfolios_ME_Prior_1_0_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/10_Portfolios_Prior_1_0_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/F-F_LT_Reversal_Factor_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/6_Portfolios_ME_Prior_60_13_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/25_Portfolios_ME_Prior_60_13_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/10_Portfolios_Prior_60_13_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Portfolios_Formed_on_AC_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/25_Portfolios_ME_AC_5x5_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Portfolios_Formed_on_BETA_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/25_Portfolios_ME_BETA_5x5_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Portfolios_Formed_on_NI_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/25_Portfolios_ME_NI_5x5_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Portfolios_Formed_on_VAR_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/25_Portfolios_ME_VAR_5x5_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Portfolios_Formed_on_RESVAR_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/25_Portfolios_ME_RESVAR_5x5_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/5_Industry_Portfolios_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/5_Industry_Portfolios_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/10_Industry_Portfolios_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/10_Industry_Portfolios_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/12_Industry_Portfolios_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/12_Industry_Portfolios_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/17_Industry_Portfolios_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/17_Industry_Portfolios_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/30_Industry_Portfolios_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/30_Industry_Portfolios_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/38_Industry_Portfolios_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/38_Industry_Portfolios_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/48_Industry_Portfolios_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/48_Industry_Portfolios_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/49_Industry_Portfolios_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/49_Industry_Portfolios_Wout_Div_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/ME_Breakpoints_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/BE-ME_Breakpoints_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/OP_Breakpoints_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/INV_Breakpoints_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/E-P_Breakpoints_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/CF-P_Breakpoints_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/D-P_Breakpoints_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Prior_2-12_Breakpoints_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_3_Factors_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_ex_US_3_Factors_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Europe_3_Factors_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Japan_3_Factors_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Asia_Pacific_ex_Japan_3_Factors_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/North_America_3_Factors_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_5_Factors_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_ex_US_5_Factors_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Europe_5_Factors_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Japan_5_Factors_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Asia_Pacific_ex_Japan_5_Factors_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/North_America_5_Factors_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_Mom_Factor_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_ex_US_Mom_Factor_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Europe_Mom_Factor_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Japan_Mom_Factor_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Asia_Pacific_ex_Japan_MOM_Factor_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/North_America_Mom_Factor_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_6_Portfolios_ME_BE-ME_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_ex_US_6_Portfolios_ME_BE-ME_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Europe_6_Portfolios_ME_BE-ME_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Japan_6_Portfolios_ME_BE-ME_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Asia_Pacific_ex_Japan_6_Portfolios_ME_BE-ME_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/North_America_6_Portfolios_ME_BE-ME_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_25_Portfolios_ME_BE-ME_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_ex_US_25_Portfolios_ME_BE-ME_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Europe_25_Portfolios_ME_BE-ME_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Japan_25_Portfolios_ME_BE-ME_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Asia_Pacific_ex_Japan_25_Portfolios_ME_BE-ME_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/North_America_25_Portfolios_ME_BE-ME_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_6_Portfolios_ME_OP_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_ex_US_6_Portfolios_ME_OP_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Europe_6_Portfolios_ME_OP_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Japan_6_Portfolios_ME_OP_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Asia_Pacific_ex_Japan_6_Portfolios_ME_OP_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/North_America_6_Portfolios_ME_OP_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_25_Portfolios_ME_OP_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_ex_US_25_Portfolios_ME_OP_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Europe_25_Portfolios_ME_OP_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Japan_25_Portfolios_ME_OP_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Asia_Pacific_ex_Japan_25_Portfolios_ME_OP_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/North_America_25_Portfolios_ME_OP_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_6_Portfolios_ME_INV_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_ex_US_6_Portfolios_ME_INV_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Europe_6_Portfolios_ME_INV_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Japan_6_Portfolios_ME_INV_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Asia_Pacific_ex_Japan_6_Portfolios_ME_INV_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/North_America_6_Portfolios_ME_INV_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_25_Portfolios_ME_INV_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_ex_US_25_Portfolios_ME_INV_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Europe_25_Portfolios_ME_INV_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Japan_25_Portfolios_ME_INV_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Asia_Pacific_ex_Japan_25_Portfolios_ME_INV_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/North_America_25_Portfolios_ME_INV_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_6_Portfolios_ME_Prior_12_2_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_ex_US_6_Portfolios_ME_Prior_12_2_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Europe_6_Portfolios_ME_Prior_12_2_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Japan_6_Portfolios_ME_Prior_12_2_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Asia_Pacific_ex_Japan_6_Portfolios_ME_Prior_12_2_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/North_America_6_Portfolios_ME_Prior_12_2_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_25_Portfolios_ME_Prior_12_2_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_ex_US_25_Portfolios_ME_Prior_12_2_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Europe_25_Portfolios_ME_Prior_12_2_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Japan_25_Portfolios_ME_Prior_12_2_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Asia_Pacific_ex_Japan_25_Portfolios_ME_Prior_12_2_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/North_America_25_Portfolios_ME_Prior_12_2_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_32_Portfolios_ME_BE-ME_OP_2x4x4_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_ex_US_32_Portfolios_ME_BE-ME_OP_2x4x4_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Europe_32_Portfolios_ME_BE-ME_OP_2x4x4_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Japan_32_Portfolios_ME_BE-ME_OP_2x4x4_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Asia_Pacific_ex_Japan_32_Portfolios_ME_BE-ME_OP_2x4x4_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/North_America_32_Portfolios_ME_BE-ME_OP_2x4x4_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_32_Portfolios_ME_BE-ME_INV(TA)_2x4x4_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_ex_US_32_Portfolios_ME_BE-ME_INV(TA)_2x4x4_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Europe_32_Portfolios_ME_BE-ME_INV(TA)_2x4x4_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Japan_32_Portfolios_ME_BE-ME_INV(TA)_2x4x4_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Asia_Pacific_ex_Japan_32_Portfolios_ME_BE-ME_INV(TA)_2x4x4_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/North_America_32_Portfolios_ME_BE-ME_INV(TA)_2x4x4_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_32_Portfolios_ME_INV(TA)_OP_2x4x4_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Developed_ex_US_32_Portfolios_ME_INV(TA)_OP_2x4x4_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Europe_32_Portfolios_ME_INV(TA)_OP_2x4x4_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Japan_32_Portfolios_ME_INV(TA)_OP_2x4x4_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Asia_Pacific_ex_Japan_32_Portfolios_ME_INV(TA)_OP_2x4x4_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/North_America_32_Portfolios_ME_INV(TA)_OP_2x4x4_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Emerging_5_Factors_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Emerging_MOM_Factor_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Emerging_Markets_6_Portfolios_ME_BE-ME_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Emerging_Markets_6_Portfolios_ME_OP_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Emerging_Markets_6_Portfolios_ME_INV_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Emerging_Markets_6_Portfolios_ME_Prior_12_2_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Emerging_Markets_4_Portfolios_BE-ME_OP_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Emerging_Markets_4_Portfolios_OP_INV_CSV.zip'
trying URL 'http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/Emerging_Markets_4_Portfolios_BE-ME_INV_CSV.zip'
Step 3: Start processing 193 csv-files

  |                                                                                                       
  |                                                                                                 |   0%
  |                                                                                                       
  |=                                                                                                |   1%
  |                                                                                                       
  |==                                                                                               |   2%
  |                                                                                                       
  |===                                                                                              |   3%
NAs introduced by coercioninput string 15 is invalid in this locale

  |                                                                                                       
  |====                                                                                             |   4%
NAs introduced by coercionNAs introduced by coercion

  |                                                                                                       
  |=====                                                                                            |   5%
NAs introduced by coercioninput string 15 is invalid in this locale

  |                                                                                                       
  |======                                                                                           |   6%
  |                                                                                                       
  |=======                                                                                          |   7%
  |                                                                                                       
  |========                                                                                         |   8%
  |                                                                                                       
  |=========                                                                                        |   9%
  |                                                                                                       
  |==========                                                                                       |  10%
input string 16 is invalid in this localeinput string 16 is invalid in this locale

  |                                                                                                       
  |===========                                                                                      |  11%
  |                                                                                                       
  |============                                                                                     |  12%
  |                                                                                                       
  |=============                                                                                    |  13%
input string 15 is invalid in this locale

  |                                                                                                       
  |==============                                                                                   |  14%
input string 15 is invalid in this locale

  |                                                                                                       
  |==============                                                                                   |  15%
  |                                                                                                       
  |===============                                                                                  |  15%
  |                                                                                                       
  |===============                                                                                  |  16%
  |                                                                                                       
  |================                                                                                 |  16%
  |                                                                                                       
  |================                                                                                 |  17%
  |                                                                                                       
  |=================                                                                                |  17%
input string 17 is invalid in this locale

  |                                                                                                       
  |=================                                                                                |  18%
input string 17 is invalid in this locale

  |                                                                                                       
  |==================                                                                               |  18%
  |                                                                                                       
  |==================                                                                               |  19%
  |                                                                                                       
  |===================                                                                              |  19%
  |                                                                                                       
  |===================                                                                              |  20%
  |                                                                                                       
  |====================                                                                             |  20%
input string 16 is invalid in this locale

  |                                                                                                       
  |====================                                                                             |  21%
input string 16 is invalid in this locale

  |                                                                                                       
  |=====================                                                                            |  21%
input string 17 is invalid in this locale

  |                                                                                                       
  |=====================                                                                            |  22%
input string 17 is invalid in this locale

  |                                                                                                       
  |======================                                                                           |  22%
  |                                                                                                       
  |======================                                                                           |  23%
  |                                                                                                       
  |=======================                                                                          |  23%
  |                                                                                                       
  |=======================                                                                          |  24%
  |                                                                                                       
  |========================                                                                         |  24%
  |                                                                                                       
  |========================                                                                         |  25%
  |                                                                                                       
  |=========================                                                                        |  25%
  |                                                                                                       
  |=========================                                                                        |  26%
  |                                                                                                       
  |==========================                                                                       |  26%
  |                                                                                                       
  |==========================                                                                       |  27%
  |                                                                                                       
  |===========================                                                                      |  27%
  |                                                                                                       
  |===========================                                                                      |  28%
  |                                                                                                       
  |============================                                                                     |  28%
  |                                                                                                       
  |============================                                                                     |  29%
  |                                                                                                       
  |=============================                                                                    |  30%
  |                                                                                                       
  |==============================                                                                   |  31%
  |                                                                                                       
  |===============================                                                                  |  32%
input string 15 is invalid in this locale

  |                                                                                                       
  |================================                                                                 |  33%
input string 15 is invalid in this locale

  |                                                                                                       
  |=================================                                                                |  34%
  |                                                                                                       
  |==================================                                                               |  35%
  |                                                                                                       
  |===================================                                                              |  36%
  |                                                                                                       
  |====================================                                                             |  37%
  |                                                                                                       
  |=====================================                                                            |  38%
  |                                                                                                       
  |======================================                                                           |  39%
  |                                                                                                       
  |=======================================                                                          |  40%
  |                                                                                                       
  |========================================                                                         |  41%
  |                                                                                                       
  |=========================================                                                        |  42%
  |                                                                                                       
  |==========================================                                                       |  43%
  |                                                                                                       
  |==========================================                                                       |  44%
  |                                                                                                       
  |===========================================                                                      |  44%
  |                                                                                                       
  |===========================================                                                      |  45%
  |                                                                                                       
  |============================================                                                     |  45%
  |                                                                                                       
  |============================================                                                     |  46%
  |                                                                                                       
  |=============================================                                                    |  46%
  |                                                                                                       
  |=============================================                                                    |  47%
  |                                                                                                       
  |==============================================                                                   |  47%
  |                                                                                                       
  |==============================================                                                   |  48%
  |                                                                                                       
  |===============================================                                                  |  48%
  |                                                                                                       
  |===============================================                                                  |  49%
  |                                                                                                       
  |================================================                                                 |  49%
  |                                                                                                       
  |================================================                                                 |  50%
  |                                                                                                       
  |=================================================                                                |  50%
  |                                                                                                       
  |=================================================                                                |  51%
  |                                                                                                       
  |==================================================                                               |  51%
  |                                                                                                       
  |==================================================                                               |  52%
  |                                                                                                       
  |===================================================                                              |  52%
  |                                                                                                       
  |===================================================                                              |  53%
  |                                                                                                       
  |====================================================                                             |  53%
  |                                                                                                       
  |====================================================                                             |  54%
  |                                                                                                       
  |=====================================================                                            |  54%
  |                                                                                                       
  |=====================================================                                            |  55%
  |                                                                                                       
  |======================================================                                           |  55%
  |                                                                                                       
  |======================================================                                           |  56%
  |                                                                                                       
  |=======================================================                                          |  56%
  |                                                                                                       
  |=======================================================                                          |  57%
  |                                                                                                       
  |========================================================                                         |  58%
  |                                                                                                       
  |=========================================================                                        |  59%
  |                                                                                                       
  |==========================================================                                       |  60%
  |                                                                                                       
  |===========================================================                                      |  61%
  |                                                                                                       
  |============================================================                                     |  62%
  |                                                                                                       
  |=============================================================                                    |  63%
  |                                                                                                       
  |==============================================================                                   |  64%
  |                                                                                                       
  |===============================================================                                  |  65%
  |                                                                                                       
  |================================================================                                 |  66%
  |                                                                                                       
  |=================================================================                                |  67%
  |                                                                                                       
  |==================================================================                               |  68%
  |                                                                                                       
  |===================================================================                              |  69%
  |                                                                                                       
  |====================================================================                             |  70%
  |                                                                                                       
  |=====================================================================                            |  71%
  |                                                                                                       
  |=====================================================================                            |  72%
  |                                                                                                       
  |======================================================================                           |  72%
  |                                                                                                       
  |======================================================================                           |  73%
  |                                                                                                       
  |=======================================================================                          |  73%
  |                                                                                                       
  |=======================================================================                          |  74%
  |                                                                                                       
  |========================================================================                         |  74%
  |                                                                                                       
  |========================================================================                         |  75%
  |                                                                                                       
  |=========================================================================                        |  75%
  |                                                                                                       
  |=========================================================================                        |  76%
  |                                                                                                       
  |==========================================================================                       |  76%
  |                                                                                                       
  |==========================================================================                       |  77%
  |                                                                                                       
  |===========================================================================                      |  77%
  |                                                                                                       
  |===========================================================================                      |  78%
  |                                                                                                       
  |============================================================================                     |  78%
  |                                                                                                       
  |============================================================================                     |  79%
  |                                                                                                       
  |=============================================================================                    |  79%
  |                                                                                                       
  |=============================================================================                    |  80%
  |                                                                                                       
  |==============================================================================                   |  80%
  |                                                                                                       
  |==============================================================================                   |  81%
  |                                                                                                       
  |===============================================================================                  |  81%
  |                                                                                                       
  |===============================================================================                  |  82%
  |                                                                                                       
  |================================================================================                 |  82%
  |                                                                                                       
  |================================================================================                 |  83%
  |                                                                                                       
  |=================================================================================                |  83%
  |                                                                                                       
  |=================================================================================                |  84%
  |                                                                                                       
  |==================================================================================               |  84%
  |                                                                                                       
  |==================================================================================               |  85%
  |                                                                                                       
  |===================================================================================              |  85%
  |                                                                                                       
  |===================================================================================              |  86%
  |                                                                                                       
  |====================================================================================             |  87%
  |                                                                                                       
  |=====================================================================================            |  88%
  |                                                                                                       
  |======================================================================================           |  89%
  |                                                                                                       
  |=======================================================================================          |  90%
  |                                                                                                       
  |========================================================================================         |  91%
  |                                                                                                       
  |=========================================================================================        |  92%
  |                                                                                                       
  |==========================================================================================       |  93%
  |                                                                                                       
  |===========================================================================================      |  94%
  |                                                                                                       
  |============================================================================================     |  95%
  |                                                                                                       
  |=============================================================================================    |  96%
  |                                                                                                       
  |==============================================================================================   |  97%
input string 17 is invalid in this locale

  |                                                                                                       
  |===============================================================================================  |  98%
input string 17 is invalid in this locale

  |                                                                                                       
  |================================================================================================ |  99%
  |                                                                                                       
  |=================================================================================================| 100%
 load(tempf2)
 ff<-FFdownload$x_Developed_ex_US_3_Factors$monthly$Temp2
 sff<-ff["2015/2019"]
 sff<-timetk::tk_tbl(ff)
 colnames(sff)[1]<-"date"
sff
require(tidyquant)
require(timetk)
Loading required package: timetk
anyNA(sp100_daily_RI)
[1] FALSE
sp100_daily_RI_prices <- gather(sp100_daily_RI, key = symbol, value= prices, "AMAZON.COM":"CHARTER COMMS.CL.A")
anyNA(sp100_daily_RI_prices)
[1] FALSE
sp100_returns_RI_60_long <- sp100_daily_RI_prices %>% mutate(prices = as.numeric(prices)) %>% group_by(symbol) %>%
  tq_transmute(select = prices,
               mutate_fun = periodReturn, 
               period="monthly", 
               type="arithmetic",
               col_rename = "Stock.returns") %>% ungroup() %>% mutate(date = as.yearmon(date))
 anyNA(sp100_returns_RI_60_long)
[1] FALSE
 sp100_returns_RI_60_long <- sp100_returns_RI_60_long[c(2,1,3)] %>% group_by(symbol)
 
 fama_french <- sff %>%
    select(date, Mkt.RF, RF) %>% mutate(date = as.yearmon(date))
  1. Now subtract the risk-free rate from all the stocks. Then estimate each stocks beta with the market: Regress all stock excess returns on the market excess return and save all betas (optimally use mutate and map in combination with lm). Estimate the mean-return for each stock and plot the return/beta-combinations. Create the security market line and include it in the plot! What do you find?
 library(tidyquant)
 library(tidyverse)
 library(PerformanceAnalytics)


 joined_data <- left_join(sp100_returns_RI_60_long, fama_french, by= c("date"))

 joined_data <- mutate(joined_data, 
       monthly_ret_rf = Stock.returns - RF)

 require(xts)
 regr_fun <- function(data_xts) {
    lm(monthly_ret_rf ~ Mkt.RF, data = as_data_frame(data_xts)) %>%
        coef()
 }

 beta_alpha <- joined_data %>% 
    tq_mutate(mutate_fun = rollapply,
              width      = 60,
              FUN        = regr_fun,
              by.column  = FALSE,
              col_rename = c("alpha", "beta"))
Problem with `mutate()` input `nested.col`.
ℹ `as_data_frame()` is deprecated as of tibble 2.0.0.
Please use `as_tibble()` instead.
The signature and semantics have changed, see `?as_tibble`.
This warning is displayed once every 8 hours.
Call `lifecycle::last_warnings()` to see where this warning was generated.
ℹ Input `nested.col` is `purrr::map(...)`.
ℹ The error occurred in group 1: symbol = "3M".`as_data_frame()` is deprecated as of tibble 2.0.0.
Please use `as_tibble()` instead.
The signature and semantics have changed, see `?as_tibble`.
This warning is displayed once every 8 hours.
Call `lifecycle::last_warnings()` to see where this warning was generated.
 beta_alpha
 beta_alpha_filter <- filter(beta_alpha, !is.na(alpha))
 symbol_beta_alpha <- beta_alpha_filter %>%
    select(symbol, alpha, beta)
 symbol_beta_alpha 
 alpha <- beta_alpha %>%
    select(symbol, alpha)
 beta <- beta_alpha_filter %>%
    select(symbol, beta)
 beta

Correction:

 library(dplyr)
 means_sp100_RI_60 <- joined_data %>%
    dplyr::group_by(symbol) %>%
    dplyr::summarize(mu = mean(monthly_ret_rf, na.rm=TRUE))
`summarise()` ungrouping output (override with `.groups` argument)
 means_sp100_RI_60
 mu.hat <- mutate(beta_alpha, 
       mu_capm = beta * mean(Mkt.RF))

 mu.hat <- filter(mu.hat, !is.na(alpha))
 mu.hat <- mu.hat  %>%
    select(symbol, alpha, beta, mu_capm)

 mu.hat <- merge(mu.hat, means_sp100_RI_60)

 sml.fit <- lm(mu_capm~beta, mu.hat)

 install.packages("plotly")
Error in install.packages : Updating loaded packages
 library(plotly)

Attaching package: ‘plotly’

The following objects are masked from ‘package:plyr’:

    arrange, mutate, rename, summarise

The following object is masked from ‘package:ggplot2’:

    last_plot

The following object is masked from ‘package:stats’:

    filter

The following object is masked from ‘package:graphics’:

    layout
 p <- plot_ly(mu.hat, x = ~beta, y = ~mu_capm, type = 'scatter', mode = 'line', text = ~paste('symbol:', symbol)) %>%
    add_markers(x = ~beta, y = ~mu)

 p
`arrange_()` is deprecated as of dplyr 0.7.0.
Please use `arrange()` instead.
See vignette('programming') for more help
This warning is displayed once every 8 hours.
Call `lifecycle::last_warnings()` to see where this warning was generated.
  1. In a next step (following both documents), we sort the stocks according to their beta and build ten value-weighted portfolios (with more or less the same number of stocks). Repeat a) for the ten portfolios. What do you observe?
 sp100_monthly_MV <- read_excel("sp100 monthly MV.xlsx")
 head(sp100_monthly_MV, n=10)

 anyNA(sp100_monthly_MV)
[1] FALSE
 sp100_monthly_MV <- gather(sp100_monthly_MV, key = symbol, value= value, "AMAZON.COM":"CHARTER COMMS.CL.A")
 anyNA(sp100_daily_RI_prices)
[1] FALSE

mean value

 mean_sp100_MV <- sp100_monthly_MV %>% 
    group_by(symbol) %>%
    summarize(mean_value = mean(value, na.rm=TRUE))
 symbol_beta_alpha_value <- merge(mean_sp100_MV, beta)
 symbol_beta_alpha_value <- arrange(symbol_beta_alpha_value, beta)
 symbol_beta_alpha_value

create weights

 Portfolio1 <- symbol_beta_alpha_value[1:10,]
 sum_weights1 <- sum(Portfolio1$mean_value)
 weight_portfolio1 <- Portfolio1$mean_value/sum_weights1

 Portfolio2 <- symbol_beta_alpha_value[11:20,]
 sum_weights2 <- sum(Portfolio2$mean_value)
 weight_portfolio2 <- Portfolio2$mean_value/sum_weights2

 Portfolio3 <- symbol_beta_alpha_value[21:30,]
 sum_weights3 <- sum(Portfolio3$mean_value)
 weight_portfolio3 <- Portfolio3$mean_value/sum_weights3

 Portfolio4 <- symbol_beta_alpha_value[31:40,]
 sum_weights4 <- sum(Portfolio4$mean_value)
 weight_portfolio4 <- Portfolio4$mean_value/sum_weights4

 Portfolio5 <- symbol_beta_alpha_value[41:50,]
 sum_weights5 <- sum(Portfolio5$mean_value)
 weight_portfolio5 <- Portfolio5$mean_value/sum_weights5

 Portfolio6 <- symbol_beta_alpha_value[51:60,]
 sum_weights6 <- sum(Portfolio6$mean_value)
 weight_portfolio6 <- Portfolio6$mean_value/sum_weights6

 Portfolio7 <- symbol_beta_alpha_value[61:70,]
 sum_weights7 <- sum(Portfolio7$mean_value)
 weight_portfolio7 <- Portfolio7$mean_value/sum_weights7

 Portfolio8 <- symbol_beta_alpha_value[71:80,]
 sum_weights8 <- sum(Portfolio8$mean_value)
 weight_portfolio8 <- Portfolio8$mean_value/sum_weights8

 Portfolio9 <- symbol_beta_alpha_value[81:90,]
 sum_weights9 <- sum(Portfolio9$mean_value)
 weight_portfolio9 <- Portfolio9$mean_value/sum_weights9

 Portfolio10 <- symbol_beta_alpha_value[91:nrow(symbol_beta_alpha_value),]
 sum_weights10 <- sum(Portfolio10$mean_value)
 weight_portfolio10 <- Portfolio10$mean_value/sum_weights10

returns Portfolio

 sp100_returns_RI_60_wide <- sp100_returns_RI_60_long %>% spread(symbol, Stock.returns)

 portfolio1_returns_wide <- sp100_returns_RI_60_wide[c("date", Portfolio1$symbol)]
 portfolio1_returns_long <- gather(portfolio1_returns_wide, key = symbol, value= returns, c(Portfolio1$symbol))
 portfolio1_returns<- portfolio1_returns_long %>%
  tq_portfolio(assets_col = symbol,
               returns_col = returns,
               weights = weight_portfolio1,
               col_rename = "Portfolio.returns") %>% mutate(Portfolio = "Portfolio 1")

 portfolio2_returns_wide <- sp100_returns_RI_60_wide[c("date", Portfolio2$symbol)]
 portfolio2_returns_long <- gather(portfolio2_returns_wide, key = symbol, value= returns, c(Portfolio2$symbol))
 portfolio2_returns<- portfolio2_returns_long %>%
  tq_portfolio(assets_col = symbol,
               returns_col = returns,
               weights = weight_portfolio2,
               col_rename = "Portfolio.returns") %>% mutate(Portfolio = "Portfolio 2")

 portfolio3_returns_wide <- sp100_returns_RI_60_wide[c("date", Portfolio3$symbol)]
 portfolio3_returns_long <- gather(portfolio3_returns_wide, key = symbol, value= returns, c(Portfolio3$symbol))
 portfolio3_returns<- portfolio3_returns_long %>%
  tq_portfolio(assets_col = symbol,
               returns_col = returns,
               weights = weight_portfolio3,
               col_rename = "Portfolio.returns") %>% mutate(Portfolio = "Portfolio 3")

 portfolio4_returns_wide <- sp100_returns_RI_60_wide[c("date", Portfolio4$symbol)]
 portfolio4_returns_long <- gather(portfolio4_returns_wide, key = symbol, value= returns, c(Portfolio4$symbol))
 portfolio4_returns<- portfolio4_returns_long %>%
  tq_portfolio(assets_col = symbol,
               returns_col = returns,
               weights = weight_portfolio4,
               col_rename = "Portfolio.returns") %>% mutate(Portfolio = "Portfolio 4")

 portfolio5_returns_wide <- sp100_returns_RI_60_wide[c("date", Portfolio5$symbol)]
 portfolio5_returns_long <- gather(portfolio5_returns_wide, key = symbol, value= returns, c(Portfolio5$symbol))
 portfolio5_returns<- portfolio5_returns_long %>%
  tq_portfolio(assets_col = symbol,
               returns_col = returns,
               weights = weight_portfolio5,
               col_rename = "Portfolio.returns") %>% mutate(Portfolio = "Portfolio 5")

 portfolio6_returns_wide <- sp100_returns_RI_60_wide[c("date", Portfolio6$symbol)]
 portfolio6_returns_long <- gather(portfolio6_returns_wide, key = symbol, value= returns, c(Portfolio6$symbol))
 portfolio6_returns<- portfolio6_returns_long %>%
  tq_portfolio(assets_col = symbol,
               returns_col = returns,
               weights = weight_portfolio6,
               col_rename = "Portfolio.returns") %>% mutate(Portfolio = "Portfolio 6")

 portfolio7_returns_wide <- sp100_returns_RI_60_wide[c("date", Portfolio7$symbol)]
 portfolio7_returns_long <- gather(portfolio7_returns_wide, key = symbol, value= returns, c(Portfolio7$symbol))
 portfolio7_returns<- portfolio7_returns_long %>%
  tq_portfolio(assets_col = symbol,
               returns_col = returns,
               weights = weight_portfolio7,
               col_rename = "Portfolio.returns") %>% mutate(Portfolio = "Portfolio 7")

 portfolio8_returns_wide <- sp100_returns_RI_60_wide[c("date", Portfolio8$symbol)]
 portfolio8_returns_long <- gather(portfolio8_returns_wide, key = symbol, value= returns, c(Portfolio8$symbol))
 portfolio8_returns<- portfolio8_returns_long %>%
  tq_portfolio(assets_col = symbol,
               returns_col = returns,
               weights = weight_portfolio8,
               col_rename = "Portfolio.returns") %>% mutate(Portfolio = "Portfolio 8")

 portfolio9_returns_wide <- sp100_returns_RI_60_wide[c("date", Portfolio9$symbol)]
 portfolio9_returns_long <- gather(portfolio9_returns_wide, key = symbol, value= returns, c(Portfolio9$symbol))
 portfolio9_returns<- portfolio9_returns_long %>%
  tq_portfolio(assets_col = symbol,
               returns_col = returns,
               weights = weight_portfolio9,
               col_rename = "Portfolio.returns") %>% mutate(Portfolio = "Portfolio 9")

 portfolio10_returns_wide <- sp100_returns_RI_60_wide[c("date", Portfolio10$symbol)]
 portfolio10_returns_long <- gather(portfolio10_returns_wide, key = symbol, value= returns, c(Portfolio10$symbol))
 portfolio10_returns<- portfolio10_returns_long %>%
  tq_portfolio(assets_col = symbol,
               returns_col = returns,
               weights = weight_portfolio10,
               col_rename = "Portfolio.returns") %>% mutate(Portfolio = "Portfolio 10")

 allportfolio_returns <- rbind(portfolio1_returns, portfolio2_returns, portfolio3_returns, portfolio4_returns, portfolio5_returns, portfolio6_returns, portfolio7_returns, portfolio8_returns, portfolio9_returns, portfolio10_returns)

 allportfolio_returns <- allportfolio_returns %>% group_by(Portfolio)
 allportfolio_returns
 joined_data_portfolio <- left_join(allportfolio_returns, fama_french, by= c("date"))

 joined_data_portfolio <- mutate(joined_data_portfolio, 
       monthly_ret_rf = Portfolio.returns - RF)

 require(xts)
 regr_fun_portfolio <- function(data_xts) {
    lm(monthly_ret_rf ~ Mkt.RF, data = as_data_frame(data_xts)) %>%
        coef()
 }

 beta_alpha_portfolio <- joined_data_portfolio %>% 
    tq_mutate(mutate_fun = rollapply,
              width      = 60,
              FUN        = regr_fun_portfolio,
              by.column  = FALSE,
              col_rename = c("alpha", "beta"))
 beta_alpha_portfolio
 beta_alpha_portfolio_filter <- filter(beta_alpha_portfolio, !is.na(alpha))
 symbol_beta_alpha_portfolio <- beta_alpha_portfolio_filter %>%
    select(Portfolio, alpha, beta)
 symbol_beta_alpha_portfolio
 alpha_portfolio <- beta_alpha_portfolio %>%
    select(Portfolio, alpha)
 beta_portfolio <- beta_alpha_portfolio %>%
    select(Portfolio, beta)

Correction:

 means_Portfolio <- joined_data_portfolio %>%
    dplyr::group_by(Portfolio) %>%
    dplyr::summarize(mu = mean(monthly_ret_rf, na.rm=TRUE))
`summarise()` ungrouping output (override with `.groups` argument)
 means_Portfolio
 return_beta_portfolio <- merge(means_Portfolio, beta_portfolio)

 mu.hat_portfolio <- mutate(beta_alpha_portfolio, 
       mu_capm_portfolio = beta * mean(Mkt.RF))

 mu.hat_portfolio <- filter(mu.hat_portfolio, !is.na(alpha))
 mu.hat_portfolio <- mu.hat_portfolio  %>%
    select(Portfolio, alpha, beta, mu_capm_portfolio)

 mu.hat_portfolio <- merge(mu.hat_portfolio, means_Portfolio)

 sml.fit_portfolio <- lm(mu_capm_portfolio~beta, mu.hat_portfolio)

 library(plotly)

 p_portfolio <- plot_ly(mu.hat_portfolio, x = ~beta, y = ~mu_capm_portfolio, type = 'scatter', mode = 'line', text = ~paste('Portfolio:', Portfolio)) %>%
    add_markers(x = ~beta, y = ~mu)

 p_portfolio
  1. In the third step you follow page 6-8 of the second document and estimate the second-pass regression with the market and then market & idiosyncratic risk. What do you observe? Present all your results in a similar fashion as in the document.
 require(xts)
 regr_fun_residuals <- function(data_xts) {
    data_xts <- lm(monthly_ret_rf ~ Mkt.RF, data = as_data_frame(data_xts))
 R <- summary(data_xts)$sigma^2
 return(R)
 }

 residuals <- joined_data %>% 
    tq_mutate(mutate_fun = rollapply,
              width      = 60,
              FUN        = regr_fun_residuals,
              by.column  = FALSE,
              col_rename = c("Residuals"))

 residuals_only <- filter(residuals, !is.na(Residuals))
 symbol_residuals <- residuals_only %>%
    select(symbol, Residuals)

 mean_MKt.RF <- joined_data %>%
    group_by(symbol) %>%
    summarize(mu_MKt_RF = mean(Mkt.RF, na.rm=TRUE))

 first <- left_join(symbol_beta_alpha, symbol_residuals, by = "symbol" )

 second <- merge(mean_MKt.RF, means_sp100_RI_60)

 all_inputs <- merge(first, second)

 second_pass_regression <- lm(mu~ beta + Residuals, all_inputs)

 summary(second_pass_regression)

Call:
lm(formula = mu ~ beta + Residuals, data = all_inputs)

Residuals:
       Min         1Q     Median         3Q        Max 
-0.0259042 -0.0053882 -0.0002212  0.0053325  0.0307786 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept) -0.065691   0.003284 -20.004   <2e-16 ***
beta         0.200369   0.266416   0.752    0.454    
Residuals    0.173445   0.388579   0.446    0.656    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.008921 on 94 degrees of freedom
Multiple R-squared:  0.01422,   Adjusted R-squared:  -0.006757 
F-statistic: 0.6778 on 2 and 94 DF,  p-value: 0.5102
 p
 require(xts)
 regr_fun_residuals <- function(data_xts) {
    data_xts <- lm(monthly_ret_rf ~ Mkt.RF, data = as_data_frame(data_xts))
 R <- summary(data_xts)$sigma^2
 return(R)
 }

 residuals_portfolio <- joined_data_portfolio %>% 
    tq_mutate(mutate_fun = rollapply,
              width      = 60,
              FUN        = regr_fun_residuals,
              by.column  = FALSE,
              col_rename = c("Residuals"))

 residuals_only_portfolio <- filter(residuals_portfolio, !is.na(Residuals))
 symbol_residuals_portfolio <- residuals_only_portfolio %>%
    select(Portfolio, Residuals)

 mean_MKt.RF_portfolio <- joined_data_portfolio %>%
    group_by(Portfolio) %>%
    summarize(mu_MKt_RF = mean(Mkt.RF, na.rm=TRUE))

 first_portfolio <- left_join(symbol_beta_alpha_portfolio, symbol_residuals_portfolio, by = "Portfolio" )

 second_portfolio <- merge(mean_MKt.RF_portfolio, means_Portfolio)

 all_inputs_portfolio <- merge(first_portfolio, second_portfolio)

 second_pass_regression_portfolio <- lm(mu~ beta + Residuals, all_inputs_portfolio)

 summary(second_pass_regression_portfolio)

Call:
lm(formula = mu ~ beta + Residuals, data = all_inputs_portfolio)

Residuals:
       Min         1Q     Median         3Q        Max 
-0.0045091 -0.0012808  0.0001732  0.0014667  0.0056631 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept) -0.078676   0.006378 -12.335 5.28e-06 ***
beta         0.133825   0.354192   0.378   0.7168    
Residuals    2.506199   1.234101   2.031   0.0818 .  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.003436 on 7 degrees of freedom
Multiple R-squared:  0.5783,    Adjusted R-squared:  0.4579 
F-statistic:   4.8 on 2 and 7 DF,  p-value: 0.04869
 p_portfolio

Exercise 2: Performance Evaluation I

Read Chapter 24 of our book. In this exercise use a Minimum Variance and a Tangecy (maxium Sharpe Ratio) portfolio calculate from your stocks, as well as the S&P500 as a benchmark (Period 2000-01-01 - 2020-01-11). For all three Investment Opportunities imagine you invest 100USD per month into the portfolio. What is the overall return this investment provides you? How much should you have investd at the bginning (one-time investment) to get the eact same overall wealth at the end of 2020? Can you plot both wealth developments over time?

First of all, I am going to download all the crucial data, which we need in order to create the three portfolios. My personal stock choice are Apple, Nividia, Microsoft, American Express, Walmart, Bank of America, Morgan Stanley, Disney, Exxon Mobile. As the benchmark we take the S&P500, regarding to the underling task.

install.packages("FinCal",dependencies=TRUE)
library(timetk, PortfolioAnalytics)
SP500 <- tq_index("SP500")
stock_names <- c("AAPL", "NVDA", "MSFT", "AXP", "WMT", "BAC", "GS","MS", "DIS", "XOM")
stock_returns <-tq_get(x = stock_names,get  = "stock.prices", from = "2000-01-01", to   = "2020-11-18") %>%
    group_by(symbol) %>%
    tq_transmute(select     = adjusted, 
                 mutate_fun = periodReturn, 
                 period     = "monthly")
unique(stock_returns$symbol)

stock_returns_xts <- stock_returns %>%
                      subset( select = c(symbol,date, monthly.returns)) %>% 
                      pivot_wider(names_from = symbol, 
                                  values_from = monthly.returns) %>% 
                      tk_xts(date_var = date, silent = TRUE)
stock_returns_xts
port <- portfolio.spec(assets=stock_names)%>%
  add.constraint(type="full_investment") %>% #In our approach we use full_investment as our task it is
  add.constraint(type="long_only") %>% #We do not take any short-selling
  add.objective(type="return", name="mean")
port

Now I defined the investment constrains for our investments, which is based on our task a full investment constrained, due to the fact that we would like to be fully invested the whole period. The long only constrain comes from the idea that we are just caring about the upper part of the efficient frontier, in order to construct the tangency portfolio, which is the most efficient way to set our 10 stocks together concerning the faced risked. So, in order words the tangency portfolio maximizes the Sharpe Ratio. The second portfolio we have to construct is the Minimum-Variance Portfolio. The “third” portfolio would be an absolute passive strategy we would just invest in the SP500.

opt_port <- optimize.portfolio(R=stock_returns_xts, portfolio=port,
                                 optimize_method="ROI", trace=TRUE)
opt_port

So, as we see we would make the most money if we would just everything in Nividia. However, we do not look for the maximum return, we look for the maximum return in relation to the taken risk.

plot(opt_port, chart.assets=TRUE, main="Maximum Return", 
      xlim=c(0,0.3), ylim=c(0,0.5))
chart.RiskReward(opt_port,return.col="mean", risk.col="sd",
                 chart.assets=TRUE, 
                 xlim=c(0, 0.25),
                 main="Maximum Return")
frontier <- create.EfficientFrontier(R=stock_returns_xts, 
                                       portfolio=port, 
                                       type="mean-StdDev")
chart.EfficientFrontier(frontier, match.col="StdDev", type="l",rf = 0, tangent.line = TRUE, chart.assets = TRUE,)

The efficient frontier is the set of optimal portfolios that offer the highest expected return for a defined level of risk or the lowest risk for a given level of expected return. Portfolios that lie below the efficient frontier are sub-optimal because they do not provide enough return for the level of risk.

port_tan <- portfolio.spec(assets=stock_names) %>%
  add.constraint(type="full_investment") %>%
  add.constraint(type = "long_only") %>%
  add.objective(type="return", name="mean")
port_tan
init.portf <- portfolio.spec(assets=stock_names)
init.portf <- add.constraint(portfolio=init.portf, type="full_investment")
init.portf <- add.constraint(portfolio=init.portf, type="long_only")
init.portf <- add.objective(portfolio=init.portf, type="return", name="mean")
init.portf <- add.objective(portfolio=init.portf, type="risk", name="StdDev")
init.portf

Maximizing the Sharpe Ratio can be formulated as a quadratic programming problem and solved very quickly using optimize_method=“ROI”. Although “StdDev” was specified as an objective, the quadratic programming problem uses the variance-covariance matrix in the objective function.

The default actin if “mean” and “StdDev” are specified as objectives with optimize_method=“ROI” is to maximize quadratic utility. If we want to maximize Sharpe Ratio, we need to pass in maxSR=TRUE to optimize the portfolio, which should lead us to the tangency portfolio.

maxSR.lo.ROI <- optimize.portfolio(R=stock_returns_xts, portfolio=init.portf, optimize_methode="ROI", maxSR=TRUE, trace=TRUE, search_size= 1000000)
maxSR.lo.ROI

It needed 17 Iterations to come as close as possible to the tangeny portfolio. We would put a big stake into Walmart, Exxon-Mobil, Disney. Although the maximum Sharpe Ratio objective can be solved quickly and accurately with optimize_method=“ROI”, it is also possible or DEoptim. These solvers have the added flexibility of using different methods to calculate the Sharpe Ratio (e.g. we could specify annualized measures of risk and return).

maxSR.lo.RP <- optimize.portfolio(R=stock_returns_xts, portfolio=init.portf, optimize_method="random", search_size=1000000, trace=TRUE)
maxSR.lo.RP
chart.RiskReward(maxSR.lo.RP, risk.col="StdDev", return.col="mean")
maxSR.lo.DE <- optimize.portfolio(R=stock_returns_xts, portfolio=init.portf, optimize_method="DEoptim", search_size=1000000, trace=TRUE)
maxSR.lo.DE
chart.RiskReward(maxSR.lo.DE, risk.col="StdDev", return.col="mean")

The Minmimum Variance Portfolio minimizing the variance of the portfolio

port_minvar <- portfolio.spec(assets=stock_names) %>%
  add.constraint(type="full_investment") %>%
  add.constraint(type = "long_only") %>%
  add.objective(type="risk", name="var")
port_minvar
opt_minvar <- optimize.portfolio(R = stock_returns_xts,portfolio = port_minvar,
                              optimize_method = "ROI", trace = TRUE, search_size= 1000000)
opt_minvar

So, as we can see we see that we would invest the majority of our capital in Walmart and Exxon Mobile, due to the low standard deviation and quiet interesting we would not invest in Nividia.

chart.RiskReward(opt_minvar,return.col="mean", risk.col="sd",
                 chart.assets=TRUE, 
                 xlim=c(0.01, 0.25),
                 main="Minimum Variance")
wts_tan <- c(0.104, 0.002, 0.120, 0.002, 0.444, 0.006, 0.026, 0.000, 0.094, 0.202)
wts_minvar <- c(0.0241, 0.0000, 0.0615, 0.0000, 0.4551, 0.0000, 0.0000, 0.0000, 0.1094, 0.3499)# Weights from the Minimum Variance Portfolio

Portfolio Returns

stock_returns

tan_port <- stock_returns %>%
    tq_portfolio(assets_col  = symbol, 
                 returns_col = monthly.returns, 
                 weights     = wts_tan, 
                 col_rename  = "Return")
tan_port
minvar_port <- stock_returns %>%
    tq_portfolio(assets_col  = symbol, 
                 returns_col = monthly.returns, 
                 weights     = wts_minvar, 
                 col_rename  = "Return")
minvar_port

For this task we take the SP500 as the benchmark.

bench_returns <- "^GSPC" %>%
    tq_get(get  = "stock.prices",
           from = "2000-01-01",
           to   = "2020-11-17") %>%
    tq_transmute(select     = adjusted, 
                 mutate_fun = periodReturn, 
                 period     = "monthly", 
                 col_rename = "Benchmark")
bench_returns
ov_tan_port <- left_join(tan_port,bench_returns,by = "date")
ov_minvar_port <- left_join(minvar_port,bench_returns,by = "date")

ov_tan_port
ov_minvar_port
ov_tan_port %>%
    tq_performance(Ra = Return, Rb = Benchmark, 
    performance_fun = table.CAPM)
ov_minvar_port %>%
    tq_performance(Ra = Return, Rb = Benchmark, 
    performance_fun = table.CAPM)
sharp_tan <- (0.1112-0)/sd(ov_tan_port$Return)
sharp_minvar <- (0.0605-0)/sd(ov_minvar_port$Return)
sharp_bench <- 1 #Checked it on the internet on an average base it is close to 1
ov_sharp <- cbind(sharp_tan, sharp_minvar, sharp_bench)
ov_sharp
tan_r <- geometric.mean(ov_tan_port$Return)
minvar_r <- geometric.mean(ov_minvar_port$Return)
bench_r <- geometric.mean(ov_minvar_port$Benchmark)
FV_tan <- FV(rate = tan_r, nper = 1:239,pv = 100,pmt = -100,type = 1)
FV_minvar <- FV(rate = minvar_r, nper = 1:239, pv = 100, pmt = -100, type=1)
FV_bench <- FV(rate=bench_r, nper = 1:239, pv = 100, pmt = -100, type = 1)
id <- c(1:239)
as.data.frame(FV_tan)
as.data.frame(id)
as.data.frame(FV_minvar)
as.data.frame(FV_bench)
ov_list <- cbind(id, FV_tan,FV_minvar,FV_bench)
ov_list <- as.data.frame(ov_list)
invest <- ov_list[239,]
invest
ggplot(ov_list, aes(x=id)) + 
  geom_line(aes(y = FV_tan), color = "darkred") + 
  geom_line(aes(y = FV_minvar), color="steelblue", linetype="twodash") +
  geom_line(aes(y=FV_bench), color="pink") +
  ggtitle("Wealth Development")

The tangency portfolio performed very good related to the others.

PV_tan <- PV(rate = tan_r,nper = 1:239,fv =-invest$FV_tan ,pmt = 0,type = 1)
PV_minvar <- PV(rate =minvar_r, nper=1:239,fv=-invest$FV_minvar,pmt=0,type=1)
PV_bench <- PV(rate=bench_r, nper=1:239, fv=-invest$FV_bench,pmt=0, type=1)
id <- c(1:239)
as.data.frame(PV_tan)
as.data.frame(id)
as.data.frame(PV_minvar)
as.data.frame(PV_bench)
ov_list <- cbind(id, PV_tan,PV_minvar,PV_bench)
ov_list <- as.data.frame(ov_list)
invest <- ov_list[239,]
invest

As we see if we would like to make an one time investment, but also the exact same amount of money as if we would invest 100 dollar per month. For the Tangency Portfolio we would need to invest 3109.721$ for the Minimium Variance Portfolio we would need to invest 4695.70$ and for the passive strategy S&P500 we would need 5082.05. So, as we can see that the intrest of intrest effect takes here part and dramatically increases the future value of our investment.

ggplot(ov_list, aes(x=id)) + 
  geom_line(aes(y = PV_tan), color = "darkred") + 
  geom_line(aes(y = PV_minvar), color="steelblue", linetype="twodash") +
  geom_line(aes(y=PV_bench), color="pink") +
  ggtitle("One time investment")

Exercise 3: Performance Evaluation II

For the same two portfolios and the appropriate benchmark calculate overall performance measures (Sharpe ratio, M2 [assume a risk-fre rate of 0], Treynor Ratio, Jensen’s Alpha and Information ratio). Interpret. Additional do the two market timing regressions (ch 24.4) and see whether your portfolios can “time” the market.

Exercise 4: Active Portfolio Management

Work through trough the demo demo(relative_ranking). Use what you lear here, form an appropriate opinion on the ranking of your assets and optimize a Minimum Variance and Maximum Sharpe ratio Portfolio. Which one performs better?

demo(relative_ranking)

data(edhec)

library(PortfolioAnalytics)
data(edhec)
R <- edhec[,1:4]
funds <- colnames(R)

#’ Construct initial portfolio with basic constraints.

init.portf <- portfolio.spec(assets=funds)
init.portf <- add.constraint(portfolio=init.portf, type="weight_sum", 
                              min_sum=0.99, max_sum=1.01)
init.portf <- add.constraint(portfolio=init.portf, type="box",min=0.05, max=0.5)
init.portf <- add.objective(portfolio=init.portf, type="risk", name="StdDev")

init.portf <- add.objective(portfolio=init.portf, type="return", name="mean")

init.portf

#’ Here we express views on the relative rank of the asset returns.

asset.rank <- c(2, 3, 1, 4)

#’ Use Meucci Fully Flexible Views framework to express views on the relative #’ order of asset returns. #’ Define prior probabilities.

p <- rep(1 / nrow(R), nrow(R))

#’ Express view on the relative ordering of asset returns

m.moments <- meucci.ranking(R, p, asset.rank)

#’ Express views using the method described in Almgren and Chriss, > #’ “Portfolios from Sorts”.

 ac.moments <- list()

ac.moments
ac.moments$mu <- ac.ranking(R, asset.rank)

Sample estimate for second moment

ac.moments$sigma <- cov(R)

#’ Generate random portfolios for use in the optimization.

rp <- random_portfolios(init.portf, 5000)

rp

#’ Run the optimization using first and second moments estimated from #’ Meucci’s Fully Flexible Views framework using the moments we calculated

opt.meucci <- optimize.portfolio(R, 
                                 init.portf,
                                 optimize_method="random", 
                                 rp=rp, 
                                 trace=TRUE,
                                 momentargs=m.moments)

opt.meucci

#’ Run the optimization using first moment estimated based on Almgren and Chriss, #’ “Portfolios from Sorts”. The second moment uses the sample estimate.

opt.ac <- optimize.portfolio(R,
                             init.portf,
                             optimize_method="random",
                             rp=rp,
                             trace=TRUE,
                             momentargs=ac.moments)

opt.ac

#’ For comparison, run the optimization using sample estimates for first and #’ second moments.

opt.sample <- optimize.portfolio(R, 
                                 init.portf, 
                                 optimize_method="random", 
                                 rp=rp,
                                 trace=TRUE)
opt.sample

#’ Here we plot the optimal weights of each optimization.

chart.Weights(combine.optimizations(list(meucci=opt.meucci, 
                                           ac=opt.ac,
                                           sample=opt.sample)), 
                
              
ylim=c(0,1), plot.type="barplot")

#’ Here we define a custom moment function to estimate moments based on #’ relative ranking views. #’ Asset are ranked according to a momentum or reversal view based on the #’ previous n periods.

moment.ranking <- function(R, n=1, momentum=TRUE, method=c("meucci", "ac")){
  
# Moment function to estimate moments based on relative ranking of 
# expected returns.
  
method <- match.arg(method)
   
   # Use the most recent n periods of returns
   tmpR <- apply(tail(R, n), 2, function(x) prod(1 + x) - 1)
   
   if(momentum){
     # Assume that the assets with the highest return will continue to outperform
     asset.rank <- order(tmpR)
   } else {
# Assume that the assets with the highest return will reverse
asset.rank <- rev(order(tmpR))
}
switch(method,
meucci = {
            # Meucci Fully Flexible Views framework
            # Prior probabilities
           p <- rep(1 / nrow(R), nrow(R))
            
            # Relative ordering view
           moments <- meucci.ranking(R, p, asset.rank)
          },
          ac = {
            # Almgren and Chriss Portfolios from Sorts
            moments <- list()
            moments$mu <- ac.ranking(R, asset.rank)
            # Sample estimate for second moment
            moments$sigma <- cov(R)
         }
   )
   return(moments)
 }

#’ Here we run out of sample backtests to test the out of sample performance using the different frameworks to express our views on relative asset return ranking.

opt.bt.meucci <- optimize.portfolio.rebalancing(R, init.portf, 
                                               optimize_method="random",  
                                               rebalance_on="quarters", 
                                               training_period=100,
                                               rp=rp,
                                               momentFUN="moment.ranking",
                                               n=2,
                                               momentum=TRUE,
                                               method="meucci")
opt.bt.ac <- optimize.portfolio.rebalancing(R, init.portf, 
optimize_method="random", 
rebalance_on="quarters", 
rp=rp,
momentFUN="moment.ranking",
n=2,
momentum=TRUE,
method="ac")

opt.bt.sample <- optimize.portfolio.rebalancing(R, init.portf, 
                                                 optimize_method="random", 
                                                 rebalance_on="quarters", 
                                                 training_period=100,
                                                 rp=rp)

#’ Compute returns and chart performance summary.

ret.meucci <- Return.portfolio(R, extractWeights(opt.bt.meucci))
ret.ac <- Return.portfolio(R, extractWeights(opt.bt.ac))
ret.sample <- Return.portfolio(R, extractWeights(opt.bt.sample))
ret <- cbind(ret.meucci, ret.ac, ret.sample)
colnames(ret) <- c("meucci.rank", "ac.rank", "sample")
charts.PerformanceSummary(ret, main="Ranking Views Performance")
LS0tCnRpdGxlOiAiUG9ydGZvbGlvbWFuYWdlbWVudCBhbmQgRmluYW5jaWFsIEFuYWx5c2lzIC0gQXNzaWdubWVudCA3IgpzdWJ0aXRsZTogIlN1Ym1pdCB1bnRpbCBNb25kYXkgMjAyMC0xMS0yMywgMTM6MDAiCmF1dGhvcjogIk1hcmtvdmljLCBNaXRzY2hlbCIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQogIApgYGB7ciBzZXR1cH0KI3JlbW90ZXM6Omluc3RhbGxfZ2l0aHViKCJicmF2ZXJvY2svRmFjdG9yQW5hbHl0aWNzIiwgIGJ1aWxkX3ZpZ25ldHRlcyA9IFRSVUUsIGZvcmNlID0gVFJVRSkKcGFjbWFuOjpwX2xvYWQodGlkeXZlcnNlLHRpZHlxdWFudCxGRmRvd25sb2FkLEZhY3RvckFuYWx5dGljcyxQZXJmb3JtYW5jZUFuYWx5dGljcyxQb3J0Zm9saW9BbmFseXRpY3MsbmxvcHRyKQpgYGAKCioqUGxlYXNlKiogcmVtZW1iZXIgdG8gcHV0IHlvdXIgYXNzaWdubWVudCBzb2x1dGlvbnMgaW4gYHJtZGAgZm9ybWF0IHVzaW5nICoqbWFueSoqIGNodW5rcyBhbmQgcHV0dGluZyByZWFkYWJsZSB0ZXh0IGluIGJldHdlZW4sIHNpbWlsYXIgdG8gbXkgZXhhbXBsZXMgZ2l2ZW4gaW4gUmVzZWFyY2ggTWV0aG9kcyBhbmQgQXNzaWdubWVudCAxIQoKRm9yIGFsbCBleGVyY2lzZXM6IFBsZWFzZSB1c2UgdGhlIEFzc2lnbm1lbnQtRm9ydW0gdG8gcG9zdCB5b3VyIHF1ZXN0aW9ucywgSSB3aWxsIHRyeSBteSBiZXN0IHRvIGhlbHAgeW91IGFsb25nIQoKIyMgRXhlcmNpc2UgMTogQW5hbHlzaW5nIHRoZSBDQVBNCgpJbiB0aGlzIGV4ZXJjaXNlIHdlIHdhbnQgdG8gZXN0aW1hdGUgdGhlIENBUE0uIFBsZWFzZSByZWFkIGNhcmVmdWxseSB0aHJvdWdoIHRoZSB0d28gZG9jdW1lbnRzIHByb3ZpZGVkIChyaWdodCBoYW5kIHNpZGU6IGZpbGVzKS4gVGhlbiB3ZSBzdGFydCB0byBjb2xsZWN0IHRoZSBuZWNlc3NhcnkgZGF0YToKICAKYSkgRnJvbSBEYXRhc3RyZWFtIGdldCB0aGUgbGFzdCAxMCB5ZWFycyBvZiBkYXRhIGZyb20gdGhlIDEwMCBzdG9ja3Mgb2YgdGhlIFMmUDEwMCB1c2luZyB0aGUgbGlzdCBgTFMmUDEwMElgIChTJlAgMTAwKTogdG90YWwgcmV0dXJuIGluZGV4IChSSSkgYW5kIG1hcmtldCBjYXAgKE1WKQoKCmBgYHtyfQpsaWJyYXJ5KHJlYWR4bCkKc3AxMDBfZGFpbHlfUkkgPC0gcmVhZF9leGNlbCgic3AxMDAgZGFpbHkgUklfMi54bHN4IikKaGVhZChzcDEwMF9kYWlseV9SSSwgbj0xMCkKYGBgCgpgYGB7cn0KbGlicmFyeShyZWFkeGwpCnNwMTAwX21vbnRobHlfTVYgPC0gcmVhZF9leGNlbCgic3AxMDAgbW9udGhseSBNVi54bHN4IikKaGVhZChzcDEwMF9tb250aGx5X01WLCBuPTEwKQpgYGAKCgpiKSBGdXJ0aGVyIGltcG9ydCB0aGUgRmFtYS1GcmVuY2gtRmFjdG9ycyBmcm9tIEtlbm5ldGggRnJlbmNocyBob21lcGFnZSAobW9udGhseSwgZS5nLiB1c2luZyBgRkZkb3dubG9hZGApLiBGcm9tIGJvdGggZGF0YXNldHMgd2Ugc2VsZWN0IGRhdGEgZm9yIHRoZSBsYXN0IChhdmFpbGFibGUpIDYwIG1vbnRocywgY2FsY3VsYXRlIHJldHVybnMgKHNpbXBsZSBwZXJjZW50YWdlKSBmb3IgdGhlIFVTLVN0b2NrcyBhbmQgZWxpbWluYXRlIHRob3NlIHN0b2NrcyB0aGF0IGhhdmUgTkFzIGZvciB0aGlzIHBlcmlvZC4KCmBgYHtyfQogdGVtcGYgPC0gdGVtcGZpbGUoZmlsZWV4dCA9ICIuUkRhdGEiKTsgdGVtcGQgPC0gdGVtcGRpcigpOyB0ZW1wdHh0IDwtIHRlbXBmaWxlKGZpbGVleHQgPSAiLnR4dCIpCiBpbnB1dGxpc3QgPC0gYygiRi1GX1Jlc2VhcmNoX0RhdGFfRmFjdG9ycyIsIkYtRl9NYXJrZXRfQmV0YSIpCiBGRmRvd25sb2FkKGV4Y2x1ZGVfZGFpbHk9VFJVRSx0ZW1wZGlyPXRlbXBkLGRvd25sb2FkPVRSVUUsZG93bmxvYWRfb25seT1GQUxTRSxpbnB1dGxpc3Q9aW5wdXRsaXN0KQogdGVtcGYyIDwtIHRlbXBmaWxlKGZpbGVleHQgPSAiLlJEYXRhIik7IHRlbXBkMiA8LSB0ZW1wZGlyKCkgCiBGRmRvd25sb2FkKG91dHB1dF9maWxlID0gdGVtcGYyLHRlbXBkaXIgPSB0ZW1wZDIsZXhjbHVkZV9kYWlseSA9IFRSVUUsIGRvd25sb2FkID0gVFJVRSwgZG93bmxvYWRfb25seT1GQUxTRSwgbGlzdHNhdmU9dGVtcHR4dCkKIGxvYWQodGVtcGYyKQogZmY8LUZGZG93bmxvYWQkeF9EZXZlbG9wZWRfZXhfVVNfM19GYWN0b3JzJG1vbnRobHkkVGVtcDIKIHNmZjwtZmZbIjIwMTUvMjAxOSJdCiBzZmY8LXRpbWV0azo6dGtfdGJsKGZmKQogY29sbmFtZXMoc2ZmKVsxXTwtImRhdGUiCmBgYAoKCmBgYHtyfQpzZmYKYGBgCgpgYGB7cn0KcmVxdWlyZSh0aWR5cXVhbnQpCnJlcXVpcmUodGltZXRrKQoKYW55TkEoc3AxMDBfZGFpbHlfUkkpCnNwMTAwX2RhaWx5X1JJX3ByaWNlcyA8LSBnYXRoZXIoc3AxMDBfZGFpbHlfUkksIGtleSA9IHN5bWJvbCwgdmFsdWU9IHByaWNlcywgIkFNQVpPTi5DT00iOiJDSEFSVEVSIENPTU1TLkNMLkEiKQphbnlOQShzcDEwMF9kYWlseV9SSV9wcmljZXMpCgpgYGAKCmBgYHtyfQpzcDEwMF9yZXR1cm5zX1JJXzYwX2xvbmcgPC0gc3AxMDBfZGFpbHlfUklfcHJpY2VzICU+JSBtdXRhdGUocHJpY2VzID0gYXMubnVtZXJpYyhwcmljZXMpKSAlPiUgZ3JvdXBfYnkoc3ltYm9sKSAlPiUKICB0cV90cmFuc211dGUoc2VsZWN0ID0gcHJpY2VzLAogICAgICAgICAgICAgICBtdXRhdGVfZnVuID0gcGVyaW9kUmV0dXJuLCAKICAgICAgICAgICAgICAgcGVyaW9kPSJtb250aGx5IiwgCiAgICAgICAgICAgICAgIHR5cGU9ImFyaXRobWV0aWMiLAogICAgICAgICAgICAgICBjb2xfcmVuYW1lID0gIlN0b2NrLnJldHVybnMiKSAlPiUgdW5ncm91cCgpICU+JSBtdXRhdGUoZGF0ZSA9IGFzLnllYXJtb24oZGF0ZSkpCiBhbnlOQShzcDEwMF9yZXR1cm5zX1JJXzYwX2xvbmcpCgogc3AxMDBfcmV0dXJuc19SSV82MF9sb25nIDwtIHNwMTAwX3JldHVybnNfUklfNjBfbG9uZ1tjKDIsMSwzKV0gJT4lIGdyb3VwX2J5KHN5bWJvbCkKIAogZmFtYV9mcmVuY2ggPC0gc2ZmICU+JQogICAgc2VsZWN0KGRhdGUsIE1rdC5SRiwgUkYpICU+JSBtdXRhdGUoZGF0ZSA9IGFzLnllYXJtb24oZGF0ZSkpCmBgYAoKCmMpIE5vdyBzdWJ0cmFjdCB0aGUgcmlzay1mcmVlIHJhdGUgZnJvbSBhbGwgdGhlIHN0b2Nrcy4gVGhlbiBlc3RpbWF0ZSBlYWNoIHN0b2NrcyBiZXRhIHdpdGggdGhlIG1hcmtldDogUmVncmVzcyBhbGwgc3RvY2sgZXhjZXNzIHJldHVybnMgb24gdGhlIG1hcmtldCBleGNlc3MgcmV0dXJuIGFuZCBzYXZlIGFsbCBiZXRhcyAob3B0aW1hbGx5IHVzZSBgbXV0YXRlYCBhbmQgYG1hcGAgaW4gY29tYmluYXRpb24gd2l0aCBgbG1gKS4gRXN0aW1hdGUgdGhlIG1lYW4tcmV0dXJuIGZvciBlYWNoIHN0b2NrIGFuZCBwbG90IHRoZSByZXR1cm4vYmV0YS1jb21iaW5hdGlvbnMuIENyZWF0ZSB0aGUgc2VjdXJpdHkgbWFya2V0IGxpbmUgYW5kIGluY2x1ZGUgaXQgaW4gdGhlIHBsb3QhIFdoYXQgZG8geW91IGZpbmQ/CgpgYGB7cn0KIGxpYnJhcnkodGlkeXF1YW50KQogbGlicmFyeSh0aWR5dmVyc2UpCiBsaWJyYXJ5KFBlcmZvcm1hbmNlQW5hbHl0aWNzKQoKCiBqb2luZWRfZGF0YSA8LSBsZWZ0X2pvaW4oc3AxMDBfcmV0dXJuc19SSV82MF9sb25nLCBmYW1hX2ZyZW5jaCwgYnk9IGMoImRhdGUiKSkKCiBqb2luZWRfZGF0YSA8LSBtdXRhdGUoam9pbmVkX2RhdGEsIAogICAgICAgbW9udGhseV9yZXRfcmYgPSBTdG9jay5yZXR1cm5zIC0gUkYpCgogcmVxdWlyZSh4dHMpCiByZWdyX2Z1biA8LSBmdW5jdGlvbihkYXRhX3h0cykgewogICAgbG0obW9udGhseV9yZXRfcmYgfiBNa3QuUkYsIGRhdGEgPSBhc19kYXRhX2ZyYW1lKGRhdGFfeHRzKSkgJT4lCiAgICAgICAgY29lZigpCiB9CgogYmV0YV9hbHBoYSA8LSBqb2luZWRfZGF0YSAlPiUgCiAgICB0cV9tdXRhdGUobXV0YXRlX2Z1biA9IHJvbGxhcHBseSwKICAgICAgICAgICAgICB3aWR0aCAgICAgID0gNjAsCiAgICAgICAgICAgICAgRlVOICAgICAgICA9IHJlZ3JfZnVuLAogICAgICAgICAgICAgIGJ5LmNvbHVtbiAgPSBGQUxTRSwKICAgICAgICAgICAgICBjb2xfcmVuYW1lID0gYygiYWxwaGEiLCAiYmV0YSIpKQoKIGJldGFfYWxwaGEKYGBgCgpgYGB7cn0KIGJldGFfYWxwaGFfZmlsdGVyIDwtIGZpbHRlcihiZXRhX2FscGhhLCAhaXMubmEoYWxwaGEpKQogc3ltYm9sX2JldGFfYWxwaGEgPC0gYmV0YV9hbHBoYV9maWx0ZXIgJT4lCiAgICBzZWxlY3Qoc3ltYm9sLCBhbHBoYSwgYmV0YSkKIHN5bWJvbF9iZXRhX2FscGhhIApgYGAKCmBgYHtyfQogYWxwaGEgPC0gYmV0YV9hbHBoYSAlPiUKICAgIHNlbGVjdChzeW1ib2wsIGFscGhhKQpgYGAKCmBgYHtyfQogYmV0YSA8LSBiZXRhX2FscGhhX2ZpbHRlciAlPiUKICAgIHNlbGVjdChzeW1ib2wsIGJldGEpCiBiZXRhCmBgYApDb3JyZWN0aW9uOgoKYGBge3J9CiBsaWJyYXJ5KGRwbHlyKQogbWVhbnNfc3AxMDBfUklfNjAgPC0gam9pbmVkX2RhdGEgJT4lCiAgICBkcGx5cjo6Z3JvdXBfYnkoc3ltYm9sKSAlPiUKICAgIGRwbHlyOjpzdW1tYXJpemUobXUgPSBtZWFuKG1vbnRobHlfcmV0X3JmLCBuYS5ybT1UUlVFKSkKIG1lYW5zX3NwMTAwX1JJXzYwCmBgYAoKCmBgYHtyfQogbXUuaGF0IDwtIG11dGF0ZShiZXRhX2FscGhhLCAKICAgICAgIG11X2NhcG0gPSBiZXRhICogbWVhbihNa3QuUkYpKQoKIG11LmhhdCA8LSBmaWx0ZXIobXUuaGF0LCAhaXMubmEoYWxwaGEpKQogbXUuaGF0IDwtIG11LmhhdCAgJT4lCiAgICBzZWxlY3Qoc3ltYm9sLCBhbHBoYSwgYmV0YSwgbXVfY2FwbSkKCiBtdS5oYXQgPC0gbWVyZ2UobXUuaGF0LCBtZWFuc19zcDEwMF9SSV82MCkKCiBzbWwuZml0IDwtIGxtKG11X2NhcG1+YmV0YSwgbXUuaGF0KQoKIGluc3RhbGwucGFja2FnZXMoInBsb3RseSIpCiBsaWJyYXJ5KHBsb3RseSkKCiBwIDwtIHBsb3RfbHkobXUuaGF0LCB4ID0gfmJldGEsIHkgPSB+bXVfY2FwbSwgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdsaW5lJywgdGV4dCA9IH5wYXN0ZSgnc3ltYm9sOicsIHN5bWJvbCkpICU+JQogICAgYWRkX21hcmtlcnMoeCA9IH5iZXRhLCB5ID0gfm11KQoKIHAKYGBgCgpkKSBJbiBhIG5leHQgc3RlcCAoZm9sbG93aW5nIGJvdGggZG9jdW1lbnRzKSwgd2Ugc29ydCB0aGUgc3RvY2tzIGFjY29yZGluZyB0byB0aGVpciBiZXRhIGFuZCBidWlsZCB0ZW4gdmFsdWUtd2VpZ2h0ZWQgcG9ydGZvbGlvcyAod2l0aCBtb3JlIG9yIGxlc3MgdGhlIHNhbWUgbnVtYmVyIG9mIHN0b2NrcykuIFJlcGVhdCBhKSBmb3IgdGhlIHRlbiBwb3J0Zm9saW9zLiBXaGF0IGRvIHlvdSBvYnNlcnZlPwoKYGBge3J9CiBzcDEwMF9tb250aGx5X01WIDwtIHJlYWRfZXhjZWwoInNwMTAwIG1vbnRobHkgTVYueGxzeCIpCiBoZWFkKHNwMTAwX21vbnRobHlfTVYsIG49MTApCgogYW55TkEoc3AxMDBfbW9udGhseV9NVikKIHNwMTAwX21vbnRobHlfTVYgPC0gZ2F0aGVyKHNwMTAwX21vbnRobHlfTVYsIGtleSA9IHN5bWJvbCwgdmFsdWU9IHZhbHVlLCAiQU1BWk9OLkNPTSI6IkNIQVJURVIgQ09NTVMuQ0wuQSIpCiBhbnlOQShzcDEwMF9kYWlseV9SSV9wcmljZXMpCmBgYAoKIG1lYW4gdmFsdWUKYGBge3J9CiBtZWFuX3NwMTAwX01WIDwtIHNwMTAwX21vbnRobHlfTVYgJT4lIAogICAgZ3JvdXBfYnkoc3ltYm9sKSAlPiUKICAgIHN1bW1hcml6ZShtZWFuX3ZhbHVlID0gbWVhbih2YWx1ZSwgbmEucm09VFJVRSkpCmBgYAoKYGBge3J9CiBzeW1ib2xfYmV0YV9hbHBoYV92YWx1ZSA8LSBtZXJnZShtZWFuX3NwMTAwX01WLCBiZXRhKQpgYGAKCmBgYHtyfQogc3ltYm9sX2JldGFfYWxwaGFfdmFsdWUgPC0gYXJyYW5nZShzeW1ib2xfYmV0YV9hbHBoYV92YWx1ZSwgYmV0YSkKIHN5bWJvbF9iZXRhX2FscGhhX3ZhbHVlCmBgYApjcmVhdGUgd2VpZ2h0cwpgYGB7cn0KIFBvcnRmb2xpbzEgPC0gc3ltYm9sX2JldGFfYWxwaGFfdmFsdWVbMToxMCxdCiBzdW1fd2VpZ2h0czEgPC0gc3VtKFBvcnRmb2xpbzEkbWVhbl92YWx1ZSkKIHdlaWdodF9wb3J0Zm9saW8xIDwtIFBvcnRmb2xpbzEkbWVhbl92YWx1ZS9zdW1fd2VpZ2h0czEKCiBQb3J0Zm9saW8yIDwtIHN5bWJvbF9iZXRhX2FscGhhX3ZhbHVlWzExOjIwLF0KIHN1bV93ZWlnaHRzMiA8LSBzdW0oUG9ydGZvbGlvMiRtZWFuX3ZhbHVlKQogd2VpZ2h0X3BvcnRmb2xpbzIgPC0gUG9ydGZvbGlvMiRtZWFuX3ZhbHVlL3N1bV93ZWlnaHRzMgoKIFBvcnRmb2xpbzMgPC0gc3ltYm9sX2JldGFfYWxwaGFfdmFsdWVbMjE6MzAsXQogc3VtX3dlaWdodHMzIDwtIHN1bShQb3J0Zm9saW8zJG1lYW5fdmFsdWUpCiB3ZWlnaHRfcG9ydGZvbGlvMyA8LSBQb3J0Zm9saW8zJG1lYW5fdmFsdWUvc3VtX3dlaWdodHMzCgogUG9ydGZvbGlvNCA8LSBzeW1ib2xfYmV0YV9hbHBoYV92YWx1ZVszMTo0MCxdCiBzdW1fd2VpZ2h0czQgPC0gc3VtKFBvcnRmb2xpbzQkbWVhbl92YWx1ZSkKIHdlaWdodF9wb3J0Zm9saW80IDwtIFBvcnRmb2xpbzQkbWVhbl92YWx1ZS9zdW1fd2VpZ2h0czQKCiBQb3J0Zm9saW81IDwtIHN5bWJvbF9iZXRhX2FscGhhX3ZhbHVlWzQxOjUwLF0KIHN1bV93ZWlnaHRzNSA8LSBzdW0oUG9ydGZvbGlvNSRtZWFuX3ZhbHVlKQogd2VpZ2h0X3BvcnRmb2xpbzUgPC0gUG9ydGZvbGlvNSRtZWFuX3ZhbHVlL3N1bV93ZWlnaHRzNQoKIFBvcnRmb2xpbzYgPC0gc3ltYm9sX2JldGFfYWxwaGFfdmFsdWVbNTE6NjAsXQogc3VtX3dlaWdodHM2IDwtIHN1bShQb3J0Zm9saW82JG1lYW5fdmFsdWUpCiB3ZWlnaHRfcG9ydGZvbGlvNiA8LSBQb3J0Zm9saW82JG1lYW5fdmFsdWUvc3VtX3dlaWdodHM2CgogUG9ydGZvbGlvNyA8LSBzeW1ib2xfYmV0YV9hbHBoYV92YWx1ZVs2MTo3MCxdCiBzdW1fd2VpZ2h0czcgPC0gc3VtKFBvcnRmb2xpbzckbWVhbl92YWx1ZSkKIHdlaWdodF9wb3J0Zm9saW83IDwtIFBvcnRmb2xpbzckbWVhbl92YWx1ZS9zdW1fd2VpZ2h0czcKCiBQb3J0Zm9saW84IDwtIHN5bWJvbF9iZXRhX2FscGhhX3ZhbHVlWzcxOjgwLF0KIHN1bV93ZWlnaHRzOCA8LSBzdW0oUG9ydGZvbGlvOCRtZWFuX3ZhbHVlKQogd2VpZ2h0X3BvcnRmb2xpbzggPC0gUG9ydGZvbGlvOCRtZWFuX3ZhbHVlL3N1bV93ZWlnaHRzOAoKIFBvcnRmb2xpbzkgPC0gc3ltYm9sX2JldGFfYWxwaGFfdmFsdWVbODE6OTAsXQogc3VtX3dlaWdodHM5IDwtIHN1bShQb3J0Zm9saW85JG1lYW5fdmFsdWUpCiB3ZWlnaHRfcG9ydGZvbGlvOSA8LSBQb3J0Zm9saW85JG1lYW5fdmFsdWUvc3VtX3dlaWdodHM5CgogUG9ydGZvbGlvMTAgPC0gc3ltYm9sX2JldGFfYWxwaGFfdmFsdWVbOTE6bnJvdyhzeW1ib2xfYmV0YV9hbHBoYV92YWx1ZSksXQogc3VtX3dlaWdodHMxMCA8LSBzdW0oUG9ydGZvbGlvMTAkbWVhbl92YWx1ZSkKIHdlaWdodF9wb3J0Zm9saW8xMCA8LSBQb3J0Zm9saW8xMCRtZWFuX3ZhbHVlL3N1bV93ZWlnaHRzMTAKYGBgCgpyZXR1cm5zIFBvcnRmb2xpbwpgYGB7cn0KIHNwMTAwX3JldHVybnNfUklfNjBfd2lkZSA8LSBzcDEwMF9yZXR1cm5zX1JJXzYwX2xvbmcgJT4lIHNwcmVhZChzeW1ib2wsIFN0b2NrLnJldHVybnMpCgogcG9ydGZvbGlvMV9yZXR1cm5zX3dpZGUgPC0gc3AxMDBfcmV0dXJuc19SSV82MF93aWRlW2MoImRhdGUiLCBQb3J0Zm9saW8xJHN5bWJvbCldCiBwb3J0Zm9saW8xX3JldHVybnNfbG9uZyA8LSBnYXRoZXIocG9ydGZvbGlvMV9yZXR1cm5zX3dpZGUsIGtleSA9IHN5bWJvbCwgdmFsdWU9IHJldHVybnMsIGMoUG9ydGZvbGlvMSRzeW1ib2wpKQogcG9ydGZvbGlvMV9yZXR1cm5zPC0gcG9ydGZvbGlvMV9yZXR1cm5zX2xvbmcgJT4lCiAgdHFfcG9ydGZvbGlvKGFzc2V0c19jb2wgPSBzeW1ib2wsCiAgICAgICAgICAgICAgIHJldHVybnNfY29sID0gcmV0dXJucywKICAgICAgICAgICAgICAgd2VpZ2h0cyA9IHdlaWdodF9wb3J0Zm9saW8xLAogICAgICAgICAgICAgICBjb2xfcmVuYW1lID0gIlBvcnRmb2xpby5yZXR1cm5zIikgJT4lIG11dGF0ZShQb3J0Zm9saW8gPSAiUG9ydGZvbGlvIDEiKQoKIHBvcnRmb2xpbzJfcmV0dXJuc193aWRlIDwtIHNwMTAwX3JldHVybnNfUklfNjBfd2lkZVtjKCJkYXRlIiwgUG9ydGZvbGlvMiRzeW1ib2wpXQogcG9ydGZvbGlvMl9yZXR1cm5zX2xvbmcgPC0gZ2F0aGVyKHBvcnRmb2xpbzJfcmV0dXJuc193aWRlLCBrZXkgPSBzeW1ib2wsIHZhbHVlPSByZXR1cm5zLCBjKFBvcnRmb2xpbzIkc3ltYm9sKSkKIHBvcnRmb2xpbzJfcmV0dXJuczwtIHBvcnRmb2xpbzJfcmV0dXJuc19sb25nICU+JQogIHRxX3BvcnRmb2xpbyhhc3NldHNfY29sID0gc3ltYm9sLAogICAgICAgICAgICAgICByZXR1cm5zX2NvbCA9IHJldHVybnMsCiAgICAgICAgICAgICAgIHdlaWdodHMgPSB3ZWlnaHRfcG9ydGZvbGlvMiwKICAgICAgICAgICAgICAgY29sX3JlbmFtZSA9ICJQb3J0Zm9saW8ucmV0dXJucyIpICU+JSBtdXRhdGUoUG9ydGZvbGlvID0gIlBvcnRmb2xpbyAyIikKCiBwb3J0Zm9saW8zX3JldHVybnNfd2lkZSA8LSBzcDEwMF9yZXR1cm5zX1JJXzYwX3dpZGVbYygiZGF0ZSIsIFBvcnRmb2xpbzMkc3ltYm9sKV0KIHBvcnRmb2xpbzNfcmV0dXJuc19sb25nIDwtIGdhdGhlcihwb3J0Zm9saW8zX3JldHVybnNfd2lkZSwga2V5ID0gc3ltYm9sLCB2YWx1ZT0gcmV0dXJucywgYyhQb3J0Zm9saW8zJHN5bWJvbCkpCiBwb3J0Zm9saW8zX3JldHVybnM8LSBwb3J0Zm9saW8zX3JldHVybnNfbG9uZyAlPiUKICB0cV9wb3J0Zm9saW8oYXNzZXRzX2NvbCA9IHN5bWJvbCwKICAgICAgICAgICAgICAgcmV0dXJuc19jb2wgPSByZXR1cm5zLAogICAgICAgICAgICAgICB3ZWlnaHRzID0gd2VpZ2h0X3BvcnRmb2xpbzMsCiAgICAgICAgICAgICAgIGNvbF9yZW5hbWUgPSAiUG9ydGZvbGlvLnJldHVybnMiKSAlPiUgbXV0YXRlKFBvcnRmb2xpbyA9ICJQb3J0Zm9saW8gMyIpCgogcG9ydGZvbGlvNF9yZXR1cm5zX3dpZGUgPC0gc3AxMDBfcmV0dXJuc19SSV82MF93aWRlW2MoImRhdGUiLCBQb3J0Zm9saW80JHN5bWJvbCldCiBwb3J0Zm9saW80X3JldHVybnNfbG9uZyA8LSBnYXRoZXIocG9ydGZvbGlvNF9yZXR1cm5zX3dpZGUsIGtleSA9IHN5bWJvbCwgdmFsdWU9IHJldHVybnMsIGMoUG9ydGZvbGlvNCRzeW1ib2wpKQogcG9ydGZvbGlvNF9yZXR1cm5zPC0gcG9ydGZvbGlvNF9yZXR1cm5zX2xvbmcgJT4lCiAgdHFfcG9ydGZvbGlvKGFzc2V0c19jb2wgPSBzeW1ib2wsCiAgICAgICAgICAgICAgIHJldHVybnNfY29sID0gcmV0dXJucywKICAgICAgICAgICAgICAgd2VpZ2h0cyA9IHdlaWdodF9wb3J0Zm9saW80LAogICAgICAgICAgICAgICBjb2xfcmVuYW1lID0gIlBvcnRmb2xpby5yZXR1cm5zIikgJT4lIG11dGF0ZShQb3J0Zm9saW8gPSAiUG9ydGZvbGlvIDQiKQoKIHBvcnRmb2xpbzVfcmV0dXJuc193aWRlIDwtIHNwMTAwX3JldHVybnNfUklfNjBfd2lkZVtjKCJkYXRlIiwgUG9ydGZvbGlvNSRzeW1ib2wpXQogcG9ydGZvbGlvNV9yZXR1cm5zX2xvbmcgPC0gZ2F0aGVyKHBvcnRmb2xpbzVfcmV0dXJuc193aWRlLCBrZXkgPSBzeW1ib2wsIHZhbHVlPSByZXR1cm5zLCBjKFBvcnRmb2xpbzUkc3ltYm9sKSkKIHBvcnRmb2xpbzVfcmV0dXJuczwtIHBvcnRmb2xpbzVfcmV0dXJuc19sb25nICU+JQogIHRxX3BvcnRmb2xpbyhhc3NldHNfY29sID0gc3ltYm9sLAogICAgICAgICAgICAgICByZXR1cm5zX2NvbCA9IHJldHVybnMsCiAgICAgICAgICAgICAgIHdlaWdodHMgPSB3ZWlnaHRfcG9ydGZvbGlvNSwKICAgICAgICAgICAgICAgY29sX3JlbmFtZSA9ICJQb3J0Zm9saW8ucmV0dXJucyIpICU+JSBtdXRhdGUoUG9ydGZvbGlvID0gIlBvcnRmb2xpbyA1IikKCiBwb3J0Zm9saW82X3JldHVybnNfd2lkZSA8LSBzcDEwMF9yZXR1cm5zX1JJXzYwX3dpZGVbYygiZGF0ZSIsIFBvcnRmb2xpbzYkc3ltYm9sKV0KIHBvcnRmb2xpbzZfcmV0dXJuc19sb25nIDwtIGdhdGhlcihwb3J0Zm9saW82X3JldHVybnNfd2lkZSwga2V5ID0gc3ltYm9sLCB2YWx1ZT0gcmV0dXJucywgYyhQb3J0Zm9saW82JHN5bWJvbCkpCiBwb3J0Zm9saW82X3JldHVybnM8LSBwb3J0Zm9saW82X3JldHVybnNfbG9uZyAlPiUKICB0cV9wb3J0Zm9saW8oYXNzZXRzX2NvbCA9IHN5bWJvbCwKICAgICAgICAgICAgICAgcmV0dXJuc19jb2wgPSByZXR1cm5zLAogICAgICAgICAgICAgICB3ZWlnaHRzID0gd2VpZ2h0X3BvcnRmb2xpbzYsCiAgICAgICAgICAgICAgIGNvbF9yZW5hbWUgPSAiUG9ydGZvbGlvLnJldHVybnMiKSAlPiUgbXV0YXRlKFBvcnRmb2xpbyA9ICJQb3J0Zm9saW8gNiIpCgogcG9ydGZvbGlvN19yZXR1cm5zX3dpZGUgPC0gc3AxMDBfcmV0dXJuc19SSV82MF93aWRlW2MoImRhdGUiLCBQb3J0Zm9saW83JHN5bWJvbCldCiBwb3J0Zm9saW83X3JldHVybnNfbG9uZyA8LSBnYXRoZXIocG9ydGZvbGlvN19yZXR1cm5zX3dpZGUsIGtleSA9IHN5bWJvbCwgdmFsdWU9IHJldHVybnMsIGMoUG9ydGZvbGlvNyRzeW1ib2wpKQogcG9ydGZvbGlvN19yZXR1cm5zPC0gcG9ydGZvbGlvN19yZXR1cm5zX2xvbmcgJT4lCiAgdHFfcG9ydGZvbGlvKGFzc2V0c19jb2wgPSBzeW1ib2wsCiAgICAgICAgICAgICAgIHJldHVybnNfY29sID0gcmV0dXJucywKICAgICAgICAgICAgICAgd2VpZ2h0cyA9IHdlaWdodF9wb3J0Zm9saW83LAogICAgICAgICAgICAgICBjb2xfcmVuYW1lID0gIlBvcnRmb2xpby5yZXR1cm5zIikgJT4lIG11dGF0ZShQb3J0Zm9saW8gPSAiUG9ydGZvbGlvIDciKQoKIHBvcnRmb2xpbzhfcmV0dXJuc193aWRlIDwtIHNwMTAwX3JldHVybnNfUklfNjBfd2lkZVtjKCJkYXRlIiwgUG9ydGZvbGlvOCRzeW1ib2wpXQogcG9ydGZvbGlvOF9yZXR1cm5zX2xvbmcgPC0gZ2F0aGVyKHBvcnRmb2xpbzhfcmV0dXJuc193aWRlLCBrZXkgPSBzeW1ib2wsIHZhbHVlPSByZXR1cm5zLCBjKFBvcnRmb2xpbzgkc3ltYm9sKSkKIHBvcnRmb2xpbzhfcmV0dXJuczwtIHBvcnRmb2xpbzhfcmV0dXJuc19sb25nICU+JQogIHRxX3BvcnRmb2xpbyhhc3NldHNfY29sID0gc3ltYm9sLAogICAgICAgICAgICAgICByZXR1cm5zX2NvbCA9IHJldHVybnMsCiAgICAgICAgICAgICAgIHdlaWdodHMgPSB3ZWlnaHRfcG9ydGZvbGlvOCwKICAgICAgICAgICAgICAgY29sX3JlbmFtZSA9ICJQb3J0Zm9saW8ucmV0dXJucyIpICU+JSBtdXRhdGUoUG9ydGZvbGlvID0gIlBvcnRmb2xpbyA4IikKCiBwb3J0Zm9saW85X3JldHVybnNfd2lkZSA8LSBzcDEwMF9yZXR1cm5zX1JJXzYwX3dpZGVbYygiZGF0ZSIsIFBvcnRmb2xpbzkkc3ltYm9sKV0KIHBvcnRmb2xpbzlfcmV0dXJuc19sb25nIDwtIGdhdGhlcihwb3J0Zm9saW85X3JldHVybnNfd2lkZSwga2V5ID0gc3ltYm9sLCB2YWx1ZT0gcmV0dXJucywgYyhQb3J0Zm9saW85JHN5bWJvbCkpCiBwb3J0Zm9saW85X3JldHVybnM8LSBwb3J0Zm9saW85X3JldHVybnNfbG9uZyAlPiUKICB0cV9wb3J0Zm9saW8oYXNzZXRzX2NvbCA9IHN5bWJvbCwKICAgICAgICAgICAgICAgcmV0dXJuc19jb2wgPSByZXR1cm5zLAogICAgICAgICAgICAgICB3ZWlnaHRzID0gd2VpZ2h0X3BvcnRmb2xpbzksCiAgICAgICAgICAgICAgIGNvbF9yZW5hbWUgPSAiUG9ydGZvbGlvLnJldHVybnMiKSAlPiUgbXV0YXRlKFBvcnRmb2xpbyA9ICJQb3J0Zm9saW8gOSIpCgogcG9ydGZvbGlvMTBfcmV0dXJuc193aWRlIDwtIHNwMTAwX3JldHVybnNfUklfNjBfd2lkZVtjKCJkYXRlIiwgUG9ydGZvbGlvMTAkc3ltYm9sKV0KIHBvcnRmb2xpbzEwX3JldHVybnNfbG9uZyA8LSBnYXRoZXIocG9ydGZvbGlvMTBfcmV0dXJuc193aWRlLCBrZXkgPSBzeW1ib2wsIHZhbHVlPSByZXR1cm5zLCBjKFBvcnRmb2xpbzEwJHN5bWJvbCkpCiBwb3J0Zm9saW8xMF9yZXR1cm5zPC0gcG9ydGZvbGlvMTBfcmV0dXJuc19sb25nICU+JQogIHRxX3BvcnRmb2xpbyhhc3NldHNfY29sID0gc3ltYm9sLAogICAgICAgICAgICAgICByZXR1cm5zX2NvbCA9IHJldHVybnMsCiAgICAgICAgICAgICAgIHdlaWdodHMgPSB3ZWlnaHRfcG9ydGZvbGlvMTAsCiAgICAgICAgICAgICAgIGNvbF9yZW5hbWUgPSAiUG9ydGZvbGlvLnJldHVybnMiKSAlPiUgbXV0YXRlKFBvcnRmb2xpbyA9ICJQb3J0Zm9saW8gMTAiKQoKIGFsbHBvcnRmb2xpb19yZXR1cm5zIDwtIHJiaW5kKHBvcnRmb2xpbzFfcmV0dXJucywgcG9ydGZvbGlvMl9yZXR1cm5zLCBwb3J0Zm9saW8zX3JldHVybnMsIHBvcnRmb2xpbzRfcmV0dXJucywgcG9ydGZvbGlvNV9yZXR1cm5zLCBwb3J0Zm9saW82X3JldHVybnMsIHBvcnRmb2xpbzdfcmV0dXJucywgcG9ydGZvbGlvOF9yZXR1cm5zLCBwb3J0Zm9saW85X3JldHVybnMsIHBvcnRmb2xpbzEwX3JldHVybnMpCgogYWxscG9ydGZvbGlvX3JldHVybnMgPC0gYWxscG9ydGZvbGlvX3JldHVybnMgJT4lIGdyb3VwX2J5KFBvcnRmb2xpbykKIGFsbHBvcnRmb2xpb19yZXR1cm5zCmBgYAoKYGBge3J9CiBqb2luZWRfZGF0YV9wb3J0Zm9saW8gPC0gbGVmdF9qb2luKGFsbHBvcnRmb2xpb19yZXR1cm5zLCBmYW1hX2ZyZW5jaCwgYnk9IGMoImRhdGUiKSkKCiBqb2luZWRfZGF0YV9wb3J0Zm9saW8gPC0gbXV0YXRlKGpvaW5lZF9kYXRhX3BvcnRmb2xpbywgCiAgICAgICBtb250aGx5X3JldF9yZiA9IFBvcnRmb2xpby5yZXR1cm5zIC0gUkYpCgogcmVxdWlyZSh4dHMpCiByZWdyX2Z1bl9wb3J0Zm9saW8gPC0gZnVuY3Rpb24oZGF0YV94dHMpIHsKICAgIGxtKG1vbnRobHlfcmV0X3JmIH4gTWt0LlJGLCBkYXRhID0gYXNfZGF0YV9mcmFtZShkYXRhX3h0cykpICU+JQogICAgICAgIGNvZWYoKQogfQoKIGJldGFfYWxwaGFfcG9ydGZvbGlvIDwtIGpvaW5lZF9kYXRhX3BvcnRmb2xpbyAlPiUgCiAgICB0cV9tdXRhdGUobXV0YXRlX2Z1biA9IHJvbGxhcHBseSwKICAgICAgICAgICAgICB3aWR0aCAgICAgID0gNjAsCiAgICAgICAgICAgICAgRlVOICAgICAgICA9IHJlZ3JfZnVuX3BvcnRmb2xpbywKICAgICAgICAgICAgICBieS5jb2x1bW4gID0gRkFMU0UsCiAgICAgICAgICAgICAgY29sX3JlbmFtZSA9IGMoImFscGhhIiwgImJldGEiKSkKIGJldGFfYWxwaGFfcG9ydGZvbGlvCmBgYAoKCmBgYHtyfQogYmV0YV9hbHBoYV9wb3J0Zm9saW9fZmlsdGVyIDwtIGZpbHRlcihiZXRhX2FscGhhX3BvcnRmb2xpbywgIWlzLm5hKGFscGhhKSkKIHN5bWJvbF9iZXRhX2FscGhhX3BvcnRmb2xpbyA8LSBiZXRhX2FscGhhX3BvcnRmb2xpb19maWx0ZXIgJT4lCiAgICBzZWxlY3QoUG9ydGZvbGlvLCBhbHBoYSwgYmV0YSkKIHN5bWJvbF9iZXRhX2FscGhhX3BvcnRmb2xpbwpgYGAKCmBgYHtyfQogYWxwaGFfcG9ydGZvbGlvIDwtIGJldGFfYWxwaGFfcG9ydGZvbGlvICU+JQogICAgc2VsZWN0KFBvcnRmb2xpbywgYWxwaGEpCmBgYAoKCmBgYHtyfQogYmV0YV9wb3J0Zm9saW8gPC0gYmV0YV9hbHBoYV9wb3J0Zm9saW8gJT4lCiAgICBzZWxlY3QoUG9ydGZvbGlvLCBiZXRhKQpgYGAKCkNvcnJlY3Rpb246CgpgYGB7cn0KIG1lYW5zX1BvcnRmb2xpbyA8LSBqb2luZWRfZGF0YV9wb3J0Zm9saW8gJT4lCiAgICBkcGx5cjo6Z3JvdXBfYnkoUG9ydGZvbGlvKSAlPiUKICAgIGRwbHlyOjpzdW1tYXJpemUobXUgPSBtZWFuKG1vbnRobHlfcmV0X3JmLCBuYS5ybT1UUlVFKSkKIG1lYW5zX1BvcnRmb2xpbwpgYGAKCmBgYHtyfQogcmV0dXJuX2JldGFfcG9ydGZvbGlvIDwtIG1lcmdlKG1lYW5zX1BvcnRmb2xpbywgYmV0YV9wb3J0Zm9saW8pCgogbXUuaGF0X3BvcnRmb2xpbyA8LSBtdXRhdGUoYmV0YV9hbHBoYV9wb3J0Zm9saW8sIAogICAgICAgbXVfY2FwbV9wb3J0Zm9saW8gPSBiZXRhICogbWVhbihNa3QuUkYpKQoKIG11LmhhdF9wb3J0Zm9saW8gPC0gZmlsdGVyKG11LmhhdF9wb3J0Zm9saW8sICFpcy5uYShhbHBoYSkpCiBtdS5oYXRfcG9ydGZvbGlvIDwtIG11LmhhdF9wb3J0Zm9saW8gICU+JQogICAgc2VsZWN0KFBvcnRmb2xpbywgYWxwaGEsIGJldGEsIG11X2NhcG1fcG9ydGZvbGlvKQoKIG11LmhhdF9wb3J0Zm9saW8gPC0gbWVyZ2UobXUuaGF0X3BvcnRmb2xpbywgbWVhbnNfUG9ydGZvbGlvKQoKIHNtbC5maXRfcG9ydGZvbGlvIDwtIGxtKG11X2NhcG1fcG9ydGZvbGlvfmJldGEsIG11LmhhdF9wb3J0Zm9saW8pCgogbGlicmFyeShwbG90bHkpCgogcF9wb3J0Zm9saW8gPC0gcGxvdF9seShtdS5oYXRfcG9ydGZvbGlvLCB4ID0gfmJldGEsIHkgPSB+bXVfY2FwbV9wb3J0Zm9saW8sIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbGluZScsIHRleHQgPSB+cGFzdGUoJ1BvcnRmb2xpbzonLCBQb3J0Zm9saW8pKSAlPiUKICAgIGFkZF9tYXJrZXJzKHggPSB+YmV0YSwgeSA9IH5tdSkKCiBwX3BvcnRmb2xpbwpgYGAKCiBlKSBJbiB0aGUgdGhpcmQgc3RlcCB5b3UgZm9sbG93IHBhZ2UgNi04IG9mIHRoZSBzZWNvbmQgZG9jdW1lbnQgYW5kIGVzdGltYXRlIHRoZSBzZWNvbmQtcGFzcyByZWdyZXNzaW9uIHdpdGggdGhlIG1hcmtldCBhbmQgdGhlbiBtYXJrZXQgJiBpZGlvc3luY3JhdGljIHJpc2suIFdoYXQgZG8geW91IG9ic2VydmU/IFByZXNlbnQgYWxsIHlvdXIgcmVzdWx0cyBpbiBhIHNpbWlsYXIgZmFzaGlvbiBhcyBpbiB0aGUgZG9jdW1lbnQuCgpgYGB7cn0KIHJlcXVpcmUoeHRzKQogcmVncl9mdW5fcmVzaWR1YWxzIDwtIGZ1bmN0aW9uKGRhdGFfeHRzKSB7CiAgICBkYXRhX3h0cyA8LSBsbShtb250aGx5X3JldF9yZiB+IE1rdC5SRiwgZGF0YSA9IGFzX2RhdGFfZnJhbWUoZGF0YV94dHMpKQogUiA8LSBzdW1tYXJ5KGRhdGFfeHRzKSRzaWdtYV4yCiByZXR1cm4oUikKIH0KCiByZXNpZHVhbHMgPC0gam9pbmVkX2RhdGEgJT4lIAogICAgdHFfbXV0YXRlKG11dGF0ZV9mdW4gPSByb2xsYXBwbHksCiAgICAgICAgICAgICAgd2lkdGggICAgICA9IDYwLAogICAgICAgICAgICAgIEZVTiAgICAgICAgPSByZWdyX2Z1bl9yZXNpZHVhbHMsCiAgICAgICAgICAgICAgYnkuY29sdW1uICA9IEZBTFNFLAogICAgICAgICAgICAgIGNvbF9yZW5hbWUgPSBjKCJSZXNpZHVhbHMiKSkKCiByZXNpZHVhbHNfb25seSA8LSBmaWx0ZXIocmVzaWR1YWxzLCAhaXMubmEoUmVzaWR1YWxzKSkKIHN5bWJvbF9yZXNpZHVhbHMgPC0gcmVzaWR1YWxzX29ubHkgJT4lCiAgICBzZWxlY3Qoc3ltYm9sLCBSZXNpZHVhbHMpCgogbWVhbl9NS3QuUkYgPC0gam9pbmVkX2RhdGEgJT4lCiAgICBncm91cF9ieShzeW1ib2wpICU+JQogICAgc3VtbWFyaXplKG11X01LdF9SRiA9IG1lYW4oTWt0LlJGLCBuYS5ybT1UUlVFKSkKCiBmaXJzdCA8LSBsZWZ0X2pvaW4oc3ltYm9sX2JldGFfYWxwaGEsIHN5bWJvbF9yZXNpZHVhbHMsIGJ5ID0gInN5bWJvbCIgKQoKIHNlY29uZCA8LSBtZXJnZShtZWFuX01LdC5SRiwgbWVhbnNfc3AxMDBfUklfNjApCgogYWxsX2lucHV0cyA8LSBtZXJnZShmaXJzdCwgc2Vjb25kKQoKIHNlY29uZF9wYXNzX3JlZ3Jlc3Npb24gPC0gbG0obXV+IGJldGEgKyBSZXNpZHVhbHMsIGFsbF9pbnB1dHMpCgogc3VtbWFyeShzZWNvbmRfcGFzc19yZWdyZXNzaW9uKQpgYGAKCmBgYHtyfQogcApgYGAKCgpgYGB7cn0KIHJlcXVpcmUoeHRzKQogcmVncl9mdW5fcmVzaWR1YWxzIDwtIGZ1bmN0aW9uKGRhdGFfeHRzKSB7CiAgICBkYXRhX3h0cyA8LSBsbShtb250aGx5X3JldF9yZiB+IE1rdC5SRiwgZGF0YSA9IGFzX2RhdGFfZnJhbWUoZGF0YV94dHMpKQogUiA8LSBzdW1tYXJ5KGRhdGFfeHRzKSRzaWdtYV4yCiByZXR1cm4oUikKIH0KCiByZXNpZHVhbHNfcG9ydGZvbGlvIDwtIGpvaW5lZF9kYXRhX3BvcnRmb2xpbyAlPiUgCiAgICB0cV9tdXRhdGUobXV0YXRlX2Z1biA9IHJvbGxhcHBseSwKICAgICAgICAgICAgICB3aWR0aCAgICAgID0gNjAsCiAgICAgICAgICAgICAgRlVOICAgICAgICA9IHJlZ3JfZnVuX3Jlc2lkdWFscywKICAgICAgICAgICAgICBieS5jb2x1bW4gID0gRkFMU0UsCiAgICAgICAgICAgICAgY29sX3JlbmFtZSA9IGMoIlJlc2lkdWFscyIpKQoKIHJlc2lkdWFsc19vbmx5X3BvcnRmb2xpbyA8LSBmaWx0ZXIocmVzaWR1YWxzX3BvcnRmb2xpbywgIWlzLm5hKFJlc2lkdWFscykpCiBzeW1ib2xfcmVzaWR1YWxzX3BvcnRmb2xpbyA8LSByZXNpZHVhbHNfb25seV9wb3J0Zm9saW8gJT4lCiAgICBzZWxlY3QoUG9ydGZvbGlvLCBSZXNpZHVhbHMpCgogbWVhbl9NS3QuUkZfcG9ydGZvbGlvIDwtIGpvaW5lZF9kYXRhX3BvcnRmb2xpbyAlPiUKICAgIGdyb3VwX2J5KFBvcnRmb2xpbykgJT4lCiAgICBzdW1tYXJpemUobXVfTUt0X1JGID0gbWVhbihNa3QuUkYsIG5hLnJtPVRSVUUpKQoKIGZpcnN0X3BvcnRmb2xpbyA8LSBsZWZ0X2pvaW4oc3ltYm9sX2JldGFfYWxwaGFfcG9ydGZvbGlvLCBzeW1ib2xfcmVzaWR1YWxzX3BvcnRmb2xpbywgYnkgPSAiUG9ydGZvbGlvIiApCgogc2Vjb25kX3BvcnRmb2xpbyA8LSBtZXJnZShtZWFuX01LdC5SRl9wb3J0Zm9saW8sIG1lYW5zX1BvcnRmb2xpbykKCiBhbGxfaW5wdXRzX3BvcnRmb2xpbyA8LSBtZXJnZShmaXJzdF9wb3J0Zm9saW8sIHNlY29uZF9wb3J0Zm9saW8pCgogc2Vjb25kX3Bhc3NfcmVncmVzc2lvbl9wb3J0Zm9saW8gPC0gbG0obXV+IGJldGEgKyBSZXNpZHVhbHMsIGFsbF9pbnB1dHNfcG9ydGZvbGlvKQoKIHN1bW1hcnkoc2Vjb25kX3Bhc3NfcmVncmVzc2lvbl9wb3J0Zm9saW8pCmBgYAoKYGBge3J9CiBwX3BvcnRmb2xpbwpgYGAKCgojIyBFeGVyY2lzZSAyOiBQZXJmb3JtYW5jZSBFdmFsdWF0aW9uIEkKClJlYWQgQ2hhcHRlciAyNCBvZiBvdXIgYm9vay4gSW4gdGhpcyBleGVyY2lzZSB1c2UgYSBNaW5pbXVtIFZhcmlhbmNlIGFuZCBhIFRhbmdlY3kgKG1heGl1bSBTaGFycGUgUmF0aW8pIHBvcnRmb2xpbyBjYWxjdWxhdGUgZnJvbSB5b3VyIHN0b2NrcywgYXMgd2VsbCBhcyB0aGUgUyZQNTAwIGFzIGEgYmVuY2htYXJrIChQZXJpb2QgMjAwMC0wMS0wMSAtIDIwMjAtMDEtMTEpLiBGb3IgYWxsIHRocmVlIEludmVzdG1lbnQgT3Bwb3J0dW5pdGllcyBpbWFnaW5lIHlvdSBpbnZlc3QgMTAwVVNEIHBlciBtb250aCBpbnRvIHRoZSBwb3J0Zm9saW8uIFdoYXQgaXMgdGhlIG92ZXJhbGwgcmV0dXJuIHRoaXMgaW52ZXN0bWVudCBwcm92aWRlcyB5b3U/IEhvdyBtdWNoIHNob3VsZCB5b3UgaGF2ZSBpbnZlc3RkIGF0IHRoZSBiZ2lubmluZyAob25lLXRpbWUgaW52ZXN0bWVudCkgdG8gZ2V0IHRoZSBlYWN0IHNhbWUgb3ZlcmFsbCB3ZWFsdGggYXQgdGhlIGVuZCBvZiAyMDIwPyBDYW4geW91IHBsb3QgYm90aCB3ZWFsdGggZGV2ZWxvcG1lbnRzIG92ZXIgdGltZT8KCkZpcnN0IG9mIGFsbCwgSSBhbSBnb2luZyB0byBkb3dubG9hZCBhbGwgdGhlIGNydWNpYWwgZGF0YSwgd2hpY2ggd2UgbmVlZCBpbiBvcmRlciB0byBjcmVhdGUgdGhlIHRocmVlIHBvcnRmb2xpb3MuIE15IHBlcnNvbmFsIHN0b2NrIGNob2ljZSBhcmUgQXBwbGUsIE5pdmlkaWEsIE1pY3Jvc29mdCwgQW1lcmljYW4gRXhwcmVzcywgV2FsbWFydCwgQmFuayBvZiBBbWVyaWNhLCBNb3JnYW4gU3RhbmxleSwgRGlzbmV5LCBFeHhvbiBNb2JpbGUuIEFzIHRoZSBiZW5jaG1hcmsgd2UgdGFrZSB0aGUgUyZQNTAwLCByZWdhcmRpbmcgdG8gdGhlIHVuZGVybGluZyB0YXNrLiAKYGBge3IgQ2hvb3NpbmcgbXkgcGVyc29uYWwgc2V0IG9mIHN0b2Nrc30KaW5zdGFsbC5wYWNrYWdlcygiRmluQ2FsIixkZXBlbmRlbmNpZXM9VFJVRSkKbGlicmFyeSh0aW1ldGssIFBvcnRmb2xpb0FuYWx5dGljcykKU1A1MDAgPC0gdHFfaW5kZXgoIlNQNTAwIikKc3RvY2tfbmFtZXMgPC0gYygiQUFQTCIsICJOVkRBIiwgIk1TRlQiLCAiQVhQIiwgIldNVCIsICJCQUMiLCAiR1MiLCJNUyIsICJESVMiLCAiWE9NIikKYGBgCgpgYGB7ciBSZXR1cm4gQ2FsY3VsYXRpb24gb2YgdGhlIHN0b2Nrc30Kc3RvY2tfcmV0dXJucyA8LXRxX2dldCh4ID0gc3RvY2tfbmFtZXMsZ2V0ICA9ICJzdG9jay5wcmljZXMiLCBmcm9tID0gIjIwMDAtMDEtMDEiLCB0byAgID0gIjIwMjAtMTEtMTgiKSAlPiUKICAgIGdyb3VwX2J5KHN5bWJvbCkgJT4lCiAgICB0cV90cmFuc211dGUoc2VsZWN0ICAgICA9IGFkanVzdGVkLCAKICAgICAgICAgICAgICAgICBtdXRhdGVfZnVuID0gcGVyaW9kUmV0dXJuLCAKICAgICAgICAgICAgICAgICBwZXJpb2QgICAgID0gIm1vbnRobHkiKQp1bmlxdWUoc3RvY2tfcmV0dXJucyRzeW1ib2wpCgpzdG9ja19yZXR1cm5zX3h0cyA8LSBzdG9ja19yZXR1cm5zICU+JQogICAgICAgICAgICAgICAgICAgICAgc3Vic2V0KCBzZWxlY3QgPSBjKHN5bWJvbCxkYXRlLCBtb250aGx5LnJldHVybnMpKSAlPiUgCiAgICAgICAgICAgICAgICAgICAgICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gc3ltYm9sLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gbW9udGhseS5yZXR1cm5zKSAlPiUgCiAgICAgICAgICAgICAgICAgICAgICB0a194dHMoZGF0ZV92YXIgPSBkYXRlLCBzaWxlbnQgPSBUUlVFKQpzdG9ja19yZXR1cm5zX3h0cwpgYGAKYGBge3IgTWF4aW11bSBSZXR1cm59CnBvcnQgPC0gcG9ydGZvbGlvLnNwZWMoYXNzZXRzPXN0b2NrX25hbWVzKSU+JQogIGFkZC5jb25zdHJhaW50KHR5cGU9ImZ1bGxfaW52ZXN0bWVudCIpICU+JSAjSW4gb3VyIGFwcHJvYWNoIHdlIHVzZSBmdWxsX2ludmVzdG1lbnQgYXMgb3VyIHRhc2sgaXQgaXMKICBhZGQuY29uc3RyYWludCh0eXBlPSJsb25nX29ubHkiKSAlPiUgI1dlIGRvIG5vdCB0YWtlIGFueSBzaG9ydC1zZWxsaW5nCiAgYWRkLm9iamVjdGl2ZSh0eXBlPSJyZXR1cm4iLCBuYW1lPSJtZWFuIikKcG9ydApgYGAKCk5vdyBJIGRlZmluZWQgdGhlIGludmVzdG1lbnQgY29uc3RyYWlucyBmb3Igb3VyIGludmVzdG1lbnRzLCB3aGljaCBpcyBiYXNlZCBvbiBvdXIgdGFzayBhIGZ1bGwgaW52ZXN0bWVudCBjb25zdHJhaW5lZCwgZHVlIHRvIHRoZSBmYWN0IHRoYXQgd2Ugd291bGQgbGlrZSB0byBiZSBmdWxseSBpbnZlc3RlZCB0aGUgd2hvbGUgcGVyaW9kLiBUaGUgbG9uZyBvbmx5IGNvbnN0cmFpbiBjb21lcyBmcm9tIHRoZSBpZGVhIHRoYXQgd2UgYXJlIGp1c3QgY2FyaW5nIGFib3V0IHRoZSB1cHBlciBwYXJ0IG9mIHRoZSBlZmZpY2llbnQgZnJvbnRpZXIsIGluIG9yZGVyIHRvIGNvbnN0cnVjdCB0aGUgdGFuZ2VuY3kgcG9ydGZvbGlvLCB3aGljaCBpcyB0aGUgX19tb3N0IGVmZmljaWVudF9fIHdheSB0byBzZXQgb3VyIDEwIHN0b2NrcyB0b2dldGhlciBjb25jZXJuaW5nIHRoZSBmYWNlZCByaXNrZWQuIFNvLCBpbiBvcmRlciB3b3JkcyB0aGUgdGFuZ2VuY3kgcG9ydGZvbGlvIG1heGltaXplcyB0aGUgU2hhcnBlIFJhdGlvLiBUaGUgc2Vjb25kIHBvcnRmb2xpbyB3ZSBoYXZlIHRvIGNvbnN0cnVjdCBpcyB0aGUgTWluaW11bS1WYXJpYW5jZSBQb3J0Zm9saW8uIFRoZSBfInRoaXJkIl8gcG9ydGZvbGlvIHdvdWxkIGJlIGFuIGFic29sdXRlIHBhc3NpdmUgc3RyYXRlZ3kgd2Ugd291bGQganVzdCBpbnZlc3QgaW4gdGhlIFNQNTAwLgoKYGBge3IgfQpvcHRfcG9ydCA8LSBvcHRpbWl6ZS5wb3J0Zm9saW8oUj1zdG9ja19yZXR1cm5zX3h0cywgcG9ydGZvbGlvPXBvcnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGltaXplX21ldGhvZD0iUk9JIiwgdHJhY2U9VFJVRSkKb3B0X3BvcnQKYGBgClNvLCBhcyB3ZSBzZWUgd2Ugd291bGQgbWFrZSB0aGUgbW9zdCBtb25leSBpZiB3ZSB3b3VsZCBqdXN0IGV2ZXJ5dGhpbmcgaW4gTml2aWRpYS4gSG93ZXZlciwgd2UgZG8gbm90IGxvb2sgZm9yIHRoZSBtYXhpbXVtIHJldHVybiwgd2UgbG9vayBmb3IgdGhlIG1heGltdW0gcmV0dXJuIGluIHJlbGF0aW9uIHRvIHRoZSB0YWtlbiByaXNrLgoKYGBge3J9CnBsb3Qob3B0X3BvcnQsIGNoYXJ0LmFzc2V0cz1UUlVFLCBtYWluPSJNYXhpbXVtIFJldHVybiIsIAogICAgICB4bGltPWMoMCwwLjMpLCB5bGltPWMoMCwwLjUpKQpgYGAKYGBge3IgUmlzayBSZXdhcmQgdHJhZGUgb2Z9CmNoYXJ0LlJpc2tSZXdhcmQob3B0X3BvcnQscmV0dXJuLmNvbD0ibWVhbiIsIHJpc2suY29sPSJzZCIsCiAgICAgICAgICAgICAgICAgY2hhcnQuYXNzZXRzPVRSVUUsIAogICAgICAgICAgICAgICAgIHhsaW09YygwLCAwLjI1KSwKICAgICAgICAgICAgICAgICBtYWluPSJNYXhpbXVtIFJldHVybiIpCmBgYAoKYGBge3J9CmZyb250aWVyIDwtIGNyZWF0ZS5FZmZpY2llbnRGcm9udGllcihSPXN0b2NrX3JldHVybnNfeHRzLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9ydGZvbGlvPXBvcnQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlPSJtZWFuLVN0ZERldiIpCmNoYXJ0LkVmZmljaWVudEZyb250aWVyKGZyb250aWVyLCBtYXRjaC5jb2w9IlN0ZERldiIsIHR5cGU9ImwiLHJmID0gMCwgdGFuZ2VudC5saW5lID0gVFJVRSwgY2hhcnQuYXNzZXRzID0gVFJVRSwpCmBgYApUaGUgZWZmaWNpZW50IGZyb250aWVyIGlzIHRoZSBzZXQgb2Ygb3B0aW1hbCBwb3J0Zm9saW9zIHRoYXQgb2ZmZXIgdGhlIGhpZ2hlc3QgZXhwZWN0ZWQgcmV0dXJuIGZvciBhIGRlZmluZWQgbGV2ZWwgb2YgcmlzayBvciB0aGUgbG93ZXN0IHJpc2sgZm9yIGEgZ2l2ZW4gbGV2ZWwgb2YgZXhwZWN0ZWQgcmV0dXJuLiBQb3J0Zm9saW9zIHRoYXQgbGllIGJlbG93IHRoZSBlZmZpY2llbnQgZnJvbnRpZXIgYXJlIHN1Yi1vcHRpbWFsIGJlY2F1c2UgdGhleSBkbyBub3QgcHJvdmlkZSBlbm91Z2ggcmV0dXJuIGZvciB0aGUgbGV2ZWwgb2Ygcmlzay4KCmBgYHtyIFRhbmdlbmN5IFBvcnRmb2xpb30KcG9ydF90YW4gPC0gcG9ydGZvbGlvLnNwZWMoYXNzZXRzPXN0b2NrX25hbWVzKSAlPiUKICBhZGQuY29uc3RyYWludCh0eXBlPSJmdWxsX2ludmVzdG1lbnQiKSAlPiUKICBhZGQuY29uc3RyYWludCh0eXBlID0gImxvbmdfb25seSIpICU+JQogIGFkZC5vYmplY3RpdmUodHlwZT0icmV0dXJuIiwgbmFtZT0ibWVhbiIpCnBvcnRfdGFuCmBgYAoKYGBge3IgQ29uc3RydWN0aW5nIHRoZSBUYW5nZW5jeSBQb3J0Zm9saW99CmluaXQucG9ydGYgPC0gcG9ydGZvbGlvLnNwZWMoYXNzZXRzPXN0b2NrX25hbWVzKQppbml0LnBvcnRmIDwtIGFkZC5jb25zdHJhaW50KHBvcnRmb2xpbz1pbml0LnBvcnRmLCB0eXBlPSJmdWxsX2ludmVzdG1lbnQiKQppbml0LnBvcnRmIDwtIGFkZC5jb25zdHJhaW50KHBvcnRmb2xpbz1pbml0LnBvcnRmLCB0eXBlPSJsb25nX29ubHkiKQppbml0LnBvcnRmIDwtIGFkZC5vYmplY3RpdmUocG9ydGZvbGlvPWluaXQucG9ydGYsIHR5cGU9InJldHVybiIsIG5hbWU9Im1lYW4iKQppbml0LnBvcnRmIDwtIGFkZC5vYmplY3RpdmUocG9ydGZvbGlvPWluaXQucG9ydGYsIHR5cGU9InJpc2siLCBuYW1lPSJTdGREZXYiKQppbml0LnBvcnRmCmBgYApNYXhpbWl6aW5nIHRoZSBTaGFycGUgUmF0aW8gY2FuIGJlIGZvcm11bGF0ZWQgYXMgYSBxdWFkcmF0aWMgcHJvZ3JhbW1pbmcgcHJvYmxlbSBhbmQgc29sdmVkIHZlcnkgcXVpY2tseSB1c2luZyBvcHRpbWl6ZV9tZXRob2Q9IlJPSSIuIEFsdGhvdWdoICJTdGREZXYiIHdhcyBzcGVjaWZpZWQgYXMgYW4gb2JqZWN0aXZlLCB0aGUgcXVhZHJhdGljIHByb2dyYW1taW5nIHByb2JsZW0gdXNlcyB0aGUgdmFyaWFuY2UtY292YXJpYW5jZSBtYXRyaXggaW4gdGhlIG9iamVjdGl2ZSBmdW5jdGlvbi4KClRoZSBkZWZhdWx0IGFjdGluIGlmICJtZWFuIiBhbmQgIlN0ZERldiIgYXJlIHNwZWNpZmllZCBhcyBvYmplY3RpdmVzIHdpdGggb3B0aW1pemVfbWV0aG9kPSJST0kiIGlzIHRvIG1heGltaXplIHF1YWRyYXRpYyB1dGlsaXR5LiBJZiB3ZSB3YW50IHRvIG1heGltaXplIFNoYXJwZSBSYXRpbywgd2UgbmVlZCB0byBwYXNzIGluIG1heFNSPVRSVUUgdG8gb3B0aW1pemUgdGhlIHBvcnRmb2xpbywgd2hpY2ggc2hvdWxkIGxlYWQgdXMgdG8gdGhlIHRhbmdlbmN5IHBvcnRmb2xpby4KCmBgYHtyIH0KbWF4U1IubG8uUk9JIDwtIG9wdGltaXplLnBvcnRmb2xpbyhSPXN0b2NrX3JldHVybnNfeHRzLCBwb3J0Zm9saW89aW5pdC5wb3J0Ziwgb3B0aW1pemVfbWV0aG9kZT0iUk9JIiwgbWF4U1I9VFJVRSwgdHJhY2U9VFJVRSwgc2VhcmNoX3NpemU9IDEwMDAwMDApCm1heFNSLmxvLlJPSQpgYGAKSXQgbmVlZGVkIDE3IEl0ZXJhdGlvbnMgdG8gY29tZSBhcyBjbG9zZSBhcyBwb3NzaWJsZSB0byB0aGUgdGFuZ2VueSBwb3J0Zm9saW8uCldlIHdvdWxkIHB1dCBhIGJpZyBzdGFrZSBpbnRvIFdhbG1hcnQsIEV4eG9uLU1vYmlsLCBEaXNuZXkuCkFsdGhvdWdoIHRoZSBtYXhpbXVtIFNoYXJwZSBSYXRpbyBvYmplY3RpdmUgY2FuIGJlIHNvbHZlZCBxdWlja2x5IGFuZCBhY2N1cmF0ZWx5IHdpdGggb3B0aW1pemVfbWV0aG9kPSJST0kiLCBpdCBpcyBhbHNvIHBvc3NpYmxlIG9yIERFb3B0aW0uIFRoZXNlIHNvbHZlcnMgaGF2ZSB0aGUgYWRkZWQgZmxleGliaWxpdHkgb2YgdXNpbmcgZGlmZmVyZW50IG1ldGhvZHMgdG8gY2FsY3VsYXRlIHRoZSBTaGFycGUgUmF0aW8gKGUuZy4gd2UgY291bGQgc3BlY2lmeSBhbm51YWxpemVkIG1lYXN1cmVzIG9mIHJpc2sgYW5kIHJldHVybikuCgpgYGB7ciBVc2UgcmFuZG9tIHBvcnRmb2xpb3MgdG8gcnVuIHRoZSBvcHRpbWl6YXRpb259Cm1heFNSLmxvLlJQIDwtIG9wdGltaXplLnBvcnRmb2xpbyhSPXN0b2NrX3JldHVybnNfeHRzLCBwb3J0Zm9saW89aW5pdC5wb3J0Ziwgb3B0aW1pemVfbWV0aG9kPSJyYW5kb20iLCBzZWFyY2hfc2l6ZT0xMDAwMDAwLCB0cmFjZT1UUlVFKQptYXhTUi5sby5SUApjaGFydC5SaXNrUmV3YXJkKG1heFNSLmxvLlJQLCByaXNrLmNvbD0iU3RkRGV2IiwgcmV0dXJuLmNvbD0ibWVhbiIpCm1heFNSLmxvLkRFIDwtIG9wdGltaXplLnBvcnRmb2xpbyhSPXN0b2NrX3JldHVybnNfeHRzLCBwb3J0Zm9saW89aW5pdC5wb3J0Ziwgb3B0aW1pemVfbWV0aG9kPSJERW9wdGltIiwgc2VhcmNoX3NpemU9MTAwMDAwMCwgdHJhY2U9VFJVRSkKbWF4U1IubG8uREUKY2hhcnQuUmlza1Jld2FyZChtYXhTUi5sby5ERSwgcmlzay5jb2w9IlN0ZERldiIsIHJldHVybi5jb2w9Im1lYW4iKQpgYGAKClRoZSBNaW5taW11bSBWYXJpYW5jZSBQb3J0Zm9saW8gbWluaW1pemluZyB0aGUgdmFyaWFuY2Ugb2YgdGhlIHBvcnRmb2xpbwoKYGBge3IgTWluaW11bSBWYXJpYW5jZX0KcG9ydF9taW52YXIgPC0gcG9ydGZvbGlvLnNwZWMoYXNzZXRzPXN0b2NrX25hbWVzKSAlPiUKICBhZGQuY29uc3RyYWludCh0eXBlPSJmdWxsX2ludmVzdG1lbnQiKSAlPiUKICBhZGQuY29uc3RyYWludCh0eXBlID0gImxvbmdfb25seSIpICU+JQogIGFkZC5vYmplY3RpdmUodHlwZT0icmlzayIsIG5hbWU9InZhciIpCnBvcnRfbWludmFyCmBgYAoKYGBge3J9Cm9wdF9taW52YXIgPC0gb3B0aW1pemUucG9ydGZvbGlvKFIgPSBzdG9ja19yZXR1cm5zX3h0cyxwb3J0Zm9saW8gPSBwb3J0X21pbnZhciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW1pemVfbWV0aG9kID0gIlJPSSIsIHRyYWNlID0gVFJVRSwgc2VhcmNoX3NpemU9IDEwMDAwMDApCm9wdF9taW52YXIKYGBgCgpTbywgYXMgd2UgY2FuIHNlZSB3ZSBzZWUgdGhhdCB3ZSB3b3VsZCBpbnZlc3QgdGhlIG1ham9yaXR5IG9mIG91ciBjYXBpdGFsIGluIFdhbG1hcnQgYW5kIEV4eG9uIE1vYmlsZSwgZHVlIHRvIHRoZSBsb3cgc3RhbmRhcmQgZGV2aWF0aW9uIGFuZCBxdWlldCBpbnRlcmVzdGluZyB3ZSB3b3VsZCBub3QgaW52ZXN0IGluIE5pdmlkaWEuCgpgYGB7cn0KY2hhcnQuUmlza1Jld2FyZChvcHRfbWludmFyLHJldHVybi5jb2w9Im1lYW4iLCByaXNrLmNvbD0ic2QiLAogICAgICAgICAgICAgICAgIGNoYXJ0LmFzc2V0cz1UUlVFLCAKICAgICAgICAgICAgICAgICB4bGltPWMoMC4wMSwgMC4yNSksCiAgICAgICAgICAgICAgICAgbWFpbj0iTWluaW11bSBWYXJpYW5jZSIpCmBgYAoKYGBge3IgV2VpZ2h0IHNldHRpbmcgZm9yIHRoZSBQb3J0Zm9saW9zfQp3dHNfdGFuIDwtIGMoMC4xMDQsIDAuMDAyLCAwLjEyMCwgMC4wMDIsIDAuNDQ0LCAwLjAwNiwgMC4wMjYsIDAuMDAwLCAwLjA5NCwgMC4yMDIpCnd0c19taW52YXIgPC0gYygwLjAyNDEsIDAuMDAwMCwgMC4wNjE1LCAwLjAwMDAsIDAuNDU1MSwgMC4wMDAwLCAwLjAwMDAsIDAuMDAwMCwgMC4xMDk0LCAwLjM0OTkpIyBXZWlnaHRzIGZyb20gdGhlIE1pbmltdW0gVmFyaWFuY2UgUG9ydGZvbGlvCmBgYAoKUG9ydGZvbGlvIFJldHVybnMKYGBge3J9CnN0b2NrX3JldHVybnMKCnRhbl9wb3J0IDwtIHN0b2NrX3JldHVybnMgJT4lCiAgICB0cV9wb3J0Zm9saW8oYXNzZXRzX2NvbCAgPSBzeW1ib2wsIAogICAgICAgICAgICAgICAgIHJldHVybnNfY29sID0gbW9udGhseS5yZXR1cm5zLCAKICAgICAgICAgICAgICAgICB3ZWlnaHRzICAgICA9IHd0c190YW4sIAogICAgICAgICAgICAgICAgIGNvbF9yZW5hbWUgID0gIlJldHVybiIpCnRhbl9wb3J0Cm1pbnZhcl9wb3J0IDwtIHN0b2NrX3JldHVybnMgJT4lCiAgICB0cV9wb3J0Zm9saW8oYXNzZXRzX2NvbCAgPSBzeW1ib2wsIAogICAgICAgICAgICAgICAgIHJldHVybnNfY29sID0gbW9udGhseS5yZXR1cm5zLCAKICAgICAgICAgICAgICAgICB3ZWlnaHRzICAgICA9IHd0c19taW52YXIsIAogICAgICAgICAgICAgICAgIGNvbF9yZW5hbWUgID0gIlJldHVybiIpCm1pbnZhcl9wb3J0CmBgYApGb3IgdGhpcyB0YXNrIHdlIHRha2UgdGhlIFNQNTAwIGFzIHRoZSBiZW5jaG1hcmsuCmBgYHtyIFNQNTAwfQpiZW5jaF9yZXR1cm5zIDwtICJeR1NQQyIgJT4lCiAgICB0cV9nZXQoZ2V0ICA9ICJzdG9jay5wcmljZXMiLAogICAgICAgICAgIGZyb20gPSAiMjAwMC0wMS0wMSIsCiAgICAgICAgICAgdG8gICA9ICIyMDIwLTExLTE3IikgJT4lCiAgICB0cV90cmFuc211dGUoc2VsZWN0ICAgICA9IGFkanVzdGVkLCAKICAgICAgICAgICAgICAgICBtdXRhdGVfZnVuID0gcGVyaW9kUmV0dXJuLCAKICAgICAgICAgICAgICAgICBwZXJpb2QgICAgID0gIm1vbnRobHkiLCAKICAgICAgICAgICAgICAgICBjb2xfcmVuYW1lID0gIkJlbmNobWFyayIpCmJlbmNoX3JldHVybnMKYGBgCmBgYHtyIE1lcmdpbmcgdGhlIGRhdGEgdG9nZXRoZXJ9Cm92X3Rhbl9wb3J0IDwtIGxlZnRfam9pbih0YW5fcG9ydCxiZW5jaF9yZXR1cm5zLGJ5ID0gImRhdGUiKQpvdl9taW52YXJfcG9ydCA8LSBsZWZ0X2pvaW4obWludmFyX3BvcnQsYmVuY2hfcmV0dXJucyxieSA9ICJkYXRlIikKCm92X3Rhbl9wb3J0Cm92X21pbnZhcl9wb3J0CmBgYApgYGB7ciBPdmVydmlldyBmb3IgdGhlIFRhbmdlbmN5IFBvcnRmb2xpb30Kb3ZfdGFuX3BvcnQgJT4lCiAgICB0cV9wZXJmb3JtYW5jZShSYSA9IFJldHVybiwgUmIgPSBCZW5jaG1hcmssIAogICAgcGVyZm9ybWFuY2VfZnVuID0gdGFibGUuQ0FQTSkKYGBgCgpgYGB7ciBPdmVydmlldyBmb3IgdGhlIE1pbmltdW0gVmFyaWFuY2V9Cm92X21pbnZhcl9wb3J0ICU+JQogICAgdHFfcGVyZm9ybWFuY2UoUmEgPSBSZXR1cm4sIFJiID0gQmVuY2htYXJrLCAKICAgIHBlcmZvcm1hbmNlX2Z1biA9IHRhYmxlLkNBUE0pCmBgYAoKYGBge3IgU2hhcnBlIFJhdGlvfQpzaGFycF90YW4gPC0gKDAuMTExMi0wKS9zZChvdl90YW5fcG9ydCRSZXR1cm4pCnNoYXJwX21pbnZhciA8LSAoMC4wNjA1LTApL3NkKG92X21pbnZhcl9wb3J0JFJldHVybikKc2hhcnBfYmVuY2ggPC0gMSAjQ2hlY2tlZCBpdCBvbiB0aGUgaW50ZXJuZXQgb24gYW4gYXZlcmFnZSBiYXNlIGl0IGlzIGNsb3NlIHRvIDEKb3Zfc2hhcnAgPC0gY2JpbmQoc2hhcnBfdGFuLCBzaGFycF9taW52YXIsIHNoYXJwX2JlbmNoKQpvdl9zaGFycApgYGAKCgpgYGB7ciBNZWFuIGNhbGN9CnRhbl9yIDwtIGdlb21ldHJpYy5tZWFuKG92X3Rhbl9wb3J0JFJldHVybikKbWludmFyX3IgPC0gZ2VvbWV0cmljLm1lYW4ob3ZfbWludmFyX3BvcnQkUmV0dXJuKQpiZW5jaF9yIDwtIGdlb21ldHJpYy5tZWFuKG92X21pbnZhcl9wb3J0JEJlbmNobWFyaykKYGBgCgpgYGB7ciBGdXR1cmUgVmFsdWV9CkZWX3RhbiA8LSBGVihyYXRlID0gdGFuX3IsIG5wZXIgPSAxOjIzOSxwdiA9IDEwMCxwbXQgPSAtMTAwLHR5cGUgPSAxKQpGVl9taW52YXIgPC0gRlYocmF0ZSA9IG1pbnZhcl9yLCBucGVyID0gMToyMzksIHB2ID0gMTAwLCBwbXQgPSAtMTAwLCB0eXBlPTEpCkZWX2JlbmNoIDwtIEZWKHJhdGU9YmVuY2hfciwgbnBlciA9IDE6MjM5LCBwdiA9IDEwMCwgcG10ID0gLTEwMCwgdHlwZSA9IDEpCmlkIDwtIGMoMToyMzkpCmFzLmRhdGEuZnJhbWUoRlZfdGFuKQphcy5kYXRhLmZyYW1lKGlkKQphcy5kYXRhLmZyYW1lKEZWX21pbnZhcikKYXMuZGF0YS5mcmFtZShGVl9iZW5jaCkKb3ZfbGlzdCA8LSBjYmluZChpZCwgRlZfdGFuLEZWX21pbnZhcixGVl9iZW5jaCkKb3ZfbGlzdCA8LSBhcy5kYXRhLmZyYW1lKG92X2xpc3QpCmludmVzdCA8LSBvdl9saXN0WzIzOSxdCmludmVzdApgYGAKCgpgYGB7ciBQbG90aW5nIHRoZSB3ZWFsdGggZGV2ZWxvcG1lbnQgb3ZlciB0aW1lfQpnZ3Bsb3Qob3ZfbGlzdCwgYWVzKHg9aWQpKSArIAogIGdlb21fbGluZShhZXMoeSA9IEZWX3RhbiksIGNvbG9yID0gImRhcmtyZWQiKSArIAogIGdlb21fbGluZShhZXMoeSA9IEZWX21pbnZhciksIGNvbG9yPSJzdGVlbGJsdWUiLCBsaW5ldHlwZT0idHdvZGFzaCIpICsKICBnZW9tX2xpbmUoYWVzKHk9RlZfYmVuY2gpLCBjb2xvcj0icGluayIpICsKICBnZ3RpdGxlKCJXZWFsdGggRGV2ZWxvcG1lbnQiKQpgYGAKVGhlIHRhbmdlbmN5IHBvcnRmb2xpbyBwZXJmb3JtZWQgdmVyeSBnb29kIHJlbGF0ZWQgdG8gdGhlIG90aGVycy4KCmBgYHtyIElmIHdlIHdvdWxkIHdhbnQgdG8gZ2V0IHRoZSBzYW1lIGFtb3VudCBvZiBtb25leSB3aXRoIGEgb25lIHRpbWUgaW52ZXN0bWVudH0KUFZfdGFuIDwtIFBWKHJhdGUgPSB0YW5fcixucGVyID0gMToyMzksZnYgPS1pbnZlc3QkRlZfdGFuICxwbXQgPSAwLHR5cGUgPSAxKQpQVl9taW52YXIgPC0gUFYocmF0ZSA9bWludmFyX3IsIG5wZXI9MToyMzksZnY9LWludmVzdCRGVl9taW52YXIscG10PTAsdHlwZT0xKQpQVl9iZW5jaCA8LSBQVihyYXRlPWJlbmNoX3IsIG5wZXI9MToyMzksIGZ2PS1pbnZlc3QkRlZfYmVuY2gscG10PTAsIHR5cGU9MSkKaWQgPC0gYygxOjIzOSkKYXMuZGF0YS5mcmFtZShQVl90YW4pCmFzLmRhdGEuZnJhbWUoaWQpCmFzLmRhdGEuZnJhbWUoUFZfbWludmFyKQphcy5kYXRhLmZyYW1lKFBWX2JlbmNoKQpvdl9saXN0IDwtIGNiaW5kKGlkLCBQVl90YW4sUFZfbWludmFyLFBWX2JlbmNoKQpvdl9saXN0IDwtIGFzLmRhdGEuZnJhbWUob3ZfbGlzdCkKaW52ZXN0IDwtIG92X2xpc3RbMjM5LF0KaW52ZXN0CmBgYApBcyB3ZSBzZWUgaWYgd2Ugd291bGQgbGlrZSB0byBtYWtlIGFuIG9uZSB0aW1lIGludmVzdG1lbnQsIGJ1dCBhbHNvIHRoZSBleGFjdCBzYW1lIGFtb3VudCBvZiBtb25leSBhcyBpZiB3ZSB3b3VsZCBpbnZlc3QgMTAwIGRvbGxhciBwZXIgbW9udGguIEZvciB0aGUgVGFuZ2VuY3kgUG9ydGZvbGlvIHdlIHdvdWxkIG5lZWQgdG8gaW52ZXN0IF9fMzEwOS43MjFfXyQgZm9yIHRoZSBNaW5pbWl1bSBWYXJpYW5jZSBQb3J0Zm9saW8gd2Ugd291bGQgbmVlZCB0byBpbnZlc3QgX180Njk1LjcwX18kIGFuZCBmb3IgdGhlIHBhc3NpdmUgc3RyYXRlZ3kgUyZQNTAwIHdlIHdvdWxkIG5lZWQgX181MDgyLjA1X18uIFNvLCBhcyB3ZSBjYW4gc2VlIHRoYXQgdGhlIGludHJlc3Qgb2YgaW50cmVzdCBlZmZlY3QgdGFrZXMgaGVyZSBwYXJ0IGFuZCBkcmFtYXRpY2FsbHkgaW5jcmVhc2VzIHRoZSBmdXR1cmUgdmFsdWUgb2Ygb3VyIGludmVzdG1lbnQuCgpgYGB7cn0KZ2dwbG90KG92X2xpc3QsIGFlcyh4PWlkKSkgKyAKICBnZW9tX2xpbmUoYWVzKHkgPSBQVl90YW4pLCBjb2xvciA9ICJkYXJrcmVkIikgKyAKICBnZW9tX2xpbmUoYWVzKHkgPSBQVl9taW52YXIpLCBjb2xvcj0ic3RlZWxibHVlIiwgbGluZXR5cGU9InR3b2Rhc2giKSArCiAgZ2VvbV9saW5lKGFlcyh5PVBWX2JlbmNoKSwgY29sb3I9InBpbmsiKSArCiAgZ2d0aXRsZSgiT25lIHRpbWUgaW52ZXN0bWVudCIpCmBgYAoKCgojIyBFeGVyY2lzZSAzOiBQZXJmb3JtYW5jZSBFdmFsdWF0aW9uIElJCgpGb3IgdGhlIHNhbWUgdHdvIHBvcnRmb2xpb3MgYW5kIHRoZSBhcHByb3ByaWF0ZSBiZW5jaG1hcmsgY2FsY3VsYXRlIG92ZXJhbGwgcGVyZm9ybWFuY2UgbWVhc3VyZXMgKFNoYXJwZSByYXRpbywgTTIgW2Fzc3VtZSBhIHJpc2stZnJlIHJhdGUgb2YgMF0sIFRyZXlub3IgUmF0aW8sIEplbnNlbidzIEFscGhhIGFuZCBJbmZvcm1hdGlvbiByYXRpbykuIEludGVycHJldC4gQWRkaXRpb25hbCBkbyB0aGUgdHdvIG1hcmtldCB0aW1pbmcgcmVncmVzc2lvbnMgKGNoIDI0LjQpIGFuZCBzZWUgd2hldGhlciB5b3VyIHBvcnRmb2xpb3MgY2FuICJ0aW1lIiB0aGUgbWFya2V0LgoKCiMjIEV4ZXJjaXNlIDQ6IEFjdGl2ZSBQb3J0Zm9saW8gTWFuYWdlbWVudAoKV29yayB0aHJvdWdoIHRyb3VnaCB0aGUgZGVtbyBgZGVtbyhyZWxhdGl2ZV9yYW5raW5nKWAuIFVzZSB3aGF0IHlvdSBsZWFyIGhlcmUsIGZvcm0gYW4gYXBwcm9wcmlhdGUgb3BpbmlvbiBvbiB0aGUgcmFua2luZyBvZiB5b3VyIGFzc2V0cyBhbmQgb3B0aW1pemUgYSBNaW5pbXVtIFZhcmlhbmNlIGFuZCBNYXhpbXVtIFNoYXJwZSByYXRpbyBQb3J0Zm9saW8uIFdoaWNoIG9uZSBwZXJmb3JtcyBiZXR0ZXI/CgpkZW1vKHJlbGF0aXZlX3JhbmtpbmcpCgpkYXRhKGVkaGVjKQpgYGB7cn0KbGlicmFyeShQb3J0Zm9saW9BbmFseXRpY3MpCmRhdGEoZWRoZWMpClIgPC0gZWRoZWNbLDE6NF0KYGBgCgpgYGB7cn0KZnVuZHMgPC0gY29sbmFtZXMoUikKYGBgCiAjJyBDb25zdHJ1Y3QgaW5pdGlhbCBwb3J0Zm9saW8gd2l0aCBiYXNpYyBjb25zdHJhaW50cy4KYGBge3J9CmluaXQucG9ydGYgPC0gcG9ydGZvbGlvLnNwZWMoYXNzZXRzPWZ1bmRzKQpgYGAKCmBgYHtyfQppbml0LnBvcnRmIDwtIGFkZC5jb25zdHJhaW50KHBvcnRmb2xpbz1pbml0LnBvcnRmLCB0eXBlPSJ3ZWlnaHRfc3VtIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbl9zdW09MC45OSwgbWF4X3N1bT0xLjAxKQpgYGAKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHBhZ2VkLnByaW50PUZBTFNFfQppbml0LnBvcnRmIDwtIGFkZC5jb25zdHJhaW50KHBvcnRmb2xpbz1pbml0LnBvcnRmLCB0eXBlPSJib3giLG1pbj0wLjA1LCBtYXg9MC41KQpgYGAKCmBgYHtyfQppbml0LnBvcnRmIDwtIGFkZC5vYmplY3RpdmUocG9ydGZvbGlvPWluaXQucG9ydGYsIHR5cGU9InJpc2siLCBuYW1lPSJTdGREZXYiKQpgYGAKCmBgYHtyfQoKaW5pdC5wb3J0ZiA8LSBhZGQub2JqZWN0aXZlKHBvcnRmb2xpbz1pbml0LnBvcnRmLCB0eXBlPSJyZXR1cm4iLCBuYW1lPSJtZWFuIikKCmluaXQucG9ydGYKYGBgCj4gIycgSGVyZSB3ZSBleHByZXNzIHZpZXdzIG9uIHRoZSByZWxhdGl2ZSByYW5rIG9mIHRoZSBhc3NldCByZXR1cm5zLgoKYGBge3J9CmFzc2V0LnJhbmsgPC0gYygyLCAzLCAxLCA0KQoKYGBgCgoKPiAjJyBVc2UgTWV1Y2NpIEZ1bGx5IEZsZXhpYmxlIFZpZXdzIGZyYW1ld29yayB0byBleHByZXNzIHZpZXdzIG9uIHRoZSByZWxhdGl2ZQo+ICMnIG9yZGVyIG9mIGFzc2V0IHJldHVybnMuCj4gIycgRGVmaW5lIHByaW9yIHByb2JhYmlsaXRpZXMuCgpgYGB7cn0KcCA8LSByZXAoMSAvIG5yb3coUiksIG5yb3coUikpCmBgYAoKPiAjJyBFeHByZXNzIHZpZXcgb24gdGhlIHJlbGF0aXZlIG9yZGVyaW5nIG9mIGFzc2V0IHJldHVybnMKCmBgYHtyfQptLm1vbWVudHMgPC0gbWV1Y2NpLnJhbmtpbmcoUiwgcCwgYXNzZXQucmFuaykKCmBgYAoKCiAjJyBFeHByZXNzIHZpZXdzIHVzaW5nIHRoZSBtZXRob2QgZGVzY3JpYmVkIGluIEFsbWdyZW4gYW5kIENocmlzcywgCj4gIycgIlBvcnRmb2xpb3MgZnJvbSBTb3J0cyIuCgpgYGB7cn0KIGFjLm1vbWVudHMgPC0gbGlzdCgpCgphYy5tb21lbnRzCmBgYAoKYGBge3J9CmFjLm1vbWVudHMkbXUgPC0gYWMucmFua2luZyhSLCBhc3NldC5yYW5rKQpgYGAKCj4gIyBTYW1wbGUgZXN0aW1hdGUgZm9yIHNlY29uZCBtb21lbnQKCmBgYHtyfQphYy5tb21lbnRzJHNpZ21hIDwtIGNvdihSKQpgYGAKCj4gIycgR2VuZXJhdGUgcmFuZG9tIHBvcnRmb2xpb3MgZm9yIHVzZSBpbiB0aGUgb3B0aW1pemF0aW9uLgoKYGBge3J9CnJwIDwtIHJhbmRvbV9wb3J0Zm9saW9zKGluaXQucG9ydGYsIDUwMDApCgpycApgYGAKPiAjJyBSdW4gdGhlIG9wdGltaXphdGlvbiB1c2luZyBmaXJzdCBhbmQgc2Vjb25kIG1vbWVudHMgZXN0aW1hdGVkIGZyb20gCj4gIycgTWV1Y2NpJ3MgRnVsbHkgRmxleGlibGUgVmlld3MgZnJhbWV3b3JrIHVzaW5nIHRoZSBtb21lbnRzIHdlIGNhbGN1bGF0ZWQKCgpgYGB7cn0Kb3B0Lm1ldWNjaSA8LSBvcHRpbWl6ZS5wb3J0Zm9saW8oUiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluaXQucG9ydGYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGltaXplX21ldGhvZD0icmFuZG9tIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJwPXJwLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhY2U9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9tZW50YXJncz1tLm1vbWVudHMpCgpvcHQubWV1Y2NpCgoKYGBgCgo+ICMnIFJ1biB0aGUgb3B0aW1pemF0aW9uIHVzaW5nIGZpcnN0IG1vbWVudCBlc3RpbWF0ZWQgYmFzZWQgb24gQWxtZ3JlbiBhbmQgQ2hyaXNzLCAKPiAjJyAiUG9ydGZvbGlvcyBmcm9tIFNvcnRzIi4gVGhlIHNlY29uZCBtb21lbnQgdXNlcyB0aGUgc2FtcGxlIGVzdGltYXRlLgoKYGBge3J9Cm9wdC5hYyA8LSBvcHRpbWl6ZS5wb3J0Zm9saW8oUiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbml0LnBvcnRmLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGltaXplX21ldGhvZD0icmFuZG9tIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBycD1ycCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjZT1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vbWVudGFyZ3M9YWMubW9tZW50cykKCm9wdC5hYwoKYGBgCj4gIycgRm9yIGNvbXBhcmlzb24sIHJ1biB0aGUgb3B0aW1pemF0aW9uIHVzaW5nIHNhbXBsZSBlc3RpbWF0ZXMgZm9yIGZpcnN0IGFuZCAKPiAjJyBzZWNvbmQgbW9tZW50cy4KCmBgYHtyfQpvcHQuc2FtcGxlIDwtIG9wdGltaXplLnBvcnRmb2xpbyhSLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5pdC5wb3J0ZiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGltaXplX21ldGhvZD0icmFuZG9tIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJwPXJwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjZT1UUlVFKQpvcHQuc2FtcGxlCgpgYGAKCgo+ICMnIEhlcmUgd2UgcGxvdCB0aGUgb3B0aW1hbCB3ZWlnaHRzIG9mIGVhY2ggb3B0aW1pemF0aW9uLgoKYGBge3J9CmNoYXJ0LldlaWdodHMoY29tYmluZS5vcHRpbWl6YXRpb25zKGxpc3QobWV1Y2NpPW9wdC5tZXVjY2ksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWM9b3B0LmFjLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlPW9wdC5zYW1wbGUpKSwgCiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAKeWxpbT1jKDAsMSksIHBsb3QudHlwZT0iYmFycGxvdCIpCgpgYGAKPiAjJyBIZXJlIHdlIGRlZmluZSBhIGN1c3RvbSBtb21lbnQgZnVuY3Rpb24gdG8gZXN0aW1hdGUgbW9tZW50cyBiYXNlZCBvbiAKPiAjJyByZWxhdGl2ZSByYW5raW5nIHZpZXdzLgo+ICMnIEFzc2V0IGFyZSByYW5rZWQgYWNjb3JkaW5nIHRvIGEgbW9tZW50dW0gb3IgcmV2ZXJzYWwgdmlldyBiYXNlZCBvbiB0aGUgCj4gIycgcHJldmlvdXMgbiBwZXJpb2RzLgoKYGBge3J9Cm1vbWVudC5yYW5raW5nIDwtIGZ1bmN0aW9uKFIsIG49MSwgbW9tZW50dW09VFJVRSwgbWV0aG9kPWMoIm1ldWNjaSIsICJhYyIpKXsKICAKIyBNb21lbnQgZnVuY3Rpb24gdG8gZXN0aW1hdGUgbW9tZW50cyBiYXNlZCBvbiByZWxhdGl2ZSByYW5raW5nIG9mIAojIGV4cGVjdGVkIHJldHVybnMuCiAgCm1ldGhvZCA8LSBtYXRjaC5hcmcobWV0aG9kKQogICAKICAgIyBVc2UgdGhlIG1vc3QgcmVjZW50IG4gcGVyaW9kcyBvZiByZXR1cm5zCiAgIHRtcFIgPC0gYXBwbHkodGFpbChSLCBuKSwgMiwgZnVuY3Rpb24oeCkgcHJvZCgxICsgeCkgLSAxKQogICAKICAgaWYobW9tZW50dW0pewogICAgICMgQXNzdW1lIHRoYXQgdGhlIGFzc2V0cyB3aXRoIHRoZSBoaWdoZXN0IHJldHVybiB3aWxsIGNvbnRpbnVlIHRvIG91dHBlcmZvcm0KICAgICBhc3NldC5yYW5rIDwtIG9yZGVyKHRtcFIpCiAgIH0gZWxzZSB7CiMgQXNzdW1lIHRoYXQgdGhlIGFzc2V0cyB3aXRoIHRoZSBoaWdoZXN0IHJldHVybiB3aWxsIHJldmVyc2UKYXNzZXQucmFuayA8LSByZXYob3JkZXIodG1wUikpCn0Kc3dpdGNoKG1ldGhvZCwKbWV1Y2NpID0gewogICAgICAgICAgICAjIE1ldWNjaSBGdWxseSBGbGV4aWJsZSBWaWV3cyBmcmFtZXdvcmsKICAgICAgICAgICAgIyBQcmlvciBwcm9iYWJpbGl0aWVzCiAgICAgICAgICAgcCA8LSByZXAoMSAvIG5yb3coUiksIG5yb3coUikpCiAgICAgICAgICAgIAogICAgICAgICAgICAjIFJlbGF0aXZlIG9yZGVyaW5nIHZpZXcKICAgICAgICAgICBtb21lbnRzIDwtIG1ldWNjaS5yYW5raW5nKFIsIHAsIGFzc2V0LnJhbmspCiAgICAgICAgICB9LAogICAgICAgICAgYWMgPSB7CiAgICAgICAgICAgICMgQWxtZ3JlbiBhbmQgQ2hyaXNzIFBvcnRmb2xpb3MgZnJvbSBTb3J0cwogICAgICAgICAgICBtb21lbnRzIDwtIGxpc3QoKQogICAgICAgICAgICBtb21lbnRzJG11IDwtIGFjLnJhbmtpbmcoUiwgYXNzZXQucmFuaykKICAgICAgICAgICAgIyBTYW1wbGUgZXN0aW1hdGUgZm9yIHNlY29uZCBtb21lbnQKICAgICAgICAgICAgbW9tZW50cyRzaWdtYSA8LSBjb3YoUikKICAgICAgICAgfQogICApCiAgIHJldHVybihtb21lbnRzKQogfQoKCmBgYAoKPiAjJyBIZXJlIHdlIHJ1biBvdXQgb2Ygc2FtcGxlIGJhY2t0ZXN0cyB0byB0ZXN0IHRoZSBvdXQgb2Ygc2FtcGxlIHBlcmZvcm1hbmNlIHVzaW5nIHRoZSBkaWZmZXJlbnQgZnJhbWV3b3JrcyB0byBleHByZXNzIG91ciB2aWV3cyBvbiByZWxhdGl2ZSBhc3NldCByZXR1cm4gcmFua2luZy4KCmBgYHtyfQpvcHQuYnQubWV1Y2NpIDwtIG9wdGltaXplLnBvcnRmb2xpby5yZWJhbGFuY2luZyhSLCBpbml0LnBvcnRmLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpbWl6ZV9tZXRob2Q9InJhbmRvbSIsICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWJhbGFuY2Vfb249InF1YXJ0ZXJzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhaW5pbmdfcGVyaW9kPTEwMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBycD1ycCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb21lbnRGVU49Im1vbWVudC5yYW5raW5nIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuPTIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9tZW50dW09VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRob2Q9Im1ldWNjaSIpCgpgYGAKYGBge3J9Cm9wdC5idC5hYyA8LSBvcHRpbWl6ZS5wb3J0Zm9saW8ucmViYWxhbmNpbmcoUiwgaW5pdC5wb3J0ZiwgCm9wdGltaXplX21ldGhvZD0icmFuZG9tIiwgCnJlYmFsYW5jZV9vbj0icXVhcnRlcnMiLCAKcnA9cnAsCm1vbWVudEZVTj0ibW9tZW50LnJhbmtpbmciLApuPTIsCm1vbWVudHVtPVRSVUUsCm1ldGhvZD0iYWMiKQpgYGAKCmBgYHtyfQoKb3B0LmJ0LnNhbXBsZSA8LSBvcHRpbWl6ZS5wb3J0Zm9saW8ucmViYWxhbmNpbmcoUiwgaW5pdC5wb3J0ZiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpbWl6ZV9tZXRob2Q9InJhbmRvbSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmViYWxhbmNlX29uPSJxdWFydGVycyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhaW5pbmdfcGVyaW9kPTEwMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJwPXJwKQpgYGAKCj4gIycgQ29tcHV0ZSByZXR1cm5zIGFuZCBjaGFydCBwZXJmb3JtYW5jZSBzdW1tYXJ5LgoKYGBge3J9CnJldC5tZXVjY2kgPC0gUmV0dXJuLnBvcnRmb2xpbyhSLCBleHRyYWN0V2VpZ2h0cyhvcHQuYnQubWV1Y2NpKSkKYGBgCgpgYGB7cn0KcmV0LmFjIDwtIFJldHVybi5wb3J0Zm9saW8oUiwgZXh0cmFjdFdlaWdodHMob3B0LmJ0LmFjKSkKYGBgCgpgYGB7cn0KcmV0LnNhbXBsZSA8LSBSZXR1cm4ucG9ydGZvbGlvKFIsIGV4dHJhY3RXZWlnaHRzKG9wdC5idC5zYW1wbGUpKQpgYGAKCmBgYHtyfQpyZXQgPC0gY2JpbmQocmV0Lm1ldWNjaSwgcmV0LmFjLCByZXQuc2FtcGxlKQpgYGAKCmBgYHtyfQpjb2xuYW1lcyhyZXQpIDwtIGMoIm1ldWNjaS5yYW5rIiwgImFjLnJhbmsiLCAic2FtcGxlIikKYGBgCgpgYGB7cn0KY2hhcnRzLlBlcmZvcm1hbmNlU3VtbWFyeShyZXQsIG1haW49IlJhbmtpbmcgVmlld3MgUGVyZm9ybWFuY2UiKQpgYGAKCgoK